diff --git a/.editorconfig b/.editorconfig new file mode 100644 index 00000000..d3a33e2f --- /dev/null +++ b/.editorconfig @@ -0,0 +1,20 @@ +root = true + +[*] +charset = utf-8 +indent_style = space +indent_size = 4 +insert_final_newline = true +trim_trailing_whitespace = true + +[*.json] +indent_style = tab + +[*.md] +trim_trailing_whitespace = false + +[*.sublime-*] +indent_style = tab + +[*.tmPreferences] +indent_style = tab diff --git a/.flake8 b/.flake8 new file mode 100644 index 00000000..59b8ae6b --- /dev/null +++ b/.flake8 @@ -0,0 +1,6 @@ +[flake8] +exclude = .*/,tests/,plugin.py,**/__init__.py +ignore = E203,E266,E501,W503 +max-complexity = 25 +max-line-length = 100 +select = B,C,E,F,W,T4,B9 diff --git a/.gitattributes b/.gitattributes new file mode 100644 index 00000000..ed7e5a64 --- /dev/null +++ b/.gitattributes @@ -0,0 +1,21 @@ +# Skip the following content from *.sublime-package files + +# Git & Github +.github/ export-ignore +.gitattributes export-ignore +.gitignore export-ignore + +# Documentation +docs/ export-ignore +samples/ export-ignore +CONTRIBUTING.md export-ignore +mcdocs.yml export-ignore + +# Unittests +tests/ export-ignore +make.cmd export-ignore + +# Settings +.editorconfig export-ignore +.flake8 export-ignore +pyproject.toml export-ignore \ No newline at end of file diff --git a/.github/workflows/ci-lint.yml b/.github/workflows/ci-lint.yml new file mode 100644 index 00000000..eeb387ca --- /dev/null +++ b/.github/workflows/ci-lint.yml @@ -0,0 +1,45 @@ +name: CI Lint + +on: + push: + branches: + - 'master' + paths: + - '**/*.json' + - '**/*.py' + - '**/*.sublime-*' + pull_request: + branches: + - '**' + paths: + - '**/*.json' + - '**/*.py' + - '**/*.sublime-*' + workflow_dispatch: + +jobs: + lint: + name: Python ${{ matrix.python }} + runs-on: ubuntu-18.04 + strategy: + matrix: + python: + - '3.3' + - '3.8' + arch: + - 'x64' + steps: + - name: Checkout Repository + uses: actions/checkout@v2 + - name: Set up Python ${{ matrix.python }} + uses: actions/setup-python@v2 + with: + python-version: ${{ matrix.python }} + architecture: ${{ matrix.arch }} + - name: Install linters + run: pip install -r tests/requirements.txt + - name: Run black + run: python -m black --check . + if: ${{ matrix.python == '3.8' }} + - name: Run flake8 + run: python -m flake8 diff --git a/.github/workflows/ci-syntax-tests.yml b/.github/workflows/ci-syntax-tests.yml new file mode 100644 index 00000000..71ca9f62 --- /dev/null +++ b/.github/workflows/ci-syntax-tests.yml @@ -0,0 +1,40 @@ +name: CI Syntax Tests + +on: + push: + branches: + - 'master' + paths: + - '.github/workflows/ci-syntax-tests.yml' + - '**.sublime-syntax' + - '**/syntax_test_*' + - '**.tmPreferences' + pull_request: + branches: + - '**' + paths: + - '.github/workflows/ci-syntax-tests.yml' + - '**.sublime-syntax' + - '**/syntax_test_*' + - '**.tmPreferences' + workflow_dispatch: + +jobs: + syntax_tests: + name: Sublime Text ${{ matrix.build }} + strategy: + matrix: + include: + - build: 3211 + packages: st3 + - build: 4107 + packages: a147e3eb6210de480d0d9a6bd6bf54931a8ba7e9 + - build: latest + packages: master + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v2 + - uses: SublimeText/syntax-test-action@v2 + with: + build: ${{ matrix.build }} + default_packages: ${{ matrix.packages }} diff --git a/.github/workflows/ci-unit-tests.yml b/.github/workflows/ci-unit-tests.yml new file mode 100644 index 00000000..3eb00c79 --- /dev/null +++ b/.github/workflows/ci-unit-tests.yml @@ -0,0 +1,41 @@ +name: CI Unit Tests + +on: + push: + branches: + - 'master' + paths: + - '**/*.json' + - '**/*.py' + - '**/*.sublime-*' + pull_request: + branches: + - '**' + paths: + - '**/*.json' + - '**/*.py' + - '**/*.sublime-*' + workflow_dispatch: + +jobs: + test: + name: Sublime Text ${{ matrix.st_version }} + runs-on: ubuntu-latest + strategy: + fail-fast: false + matrix: + st_version: [3, 4] + container: + image: sublimetext/unittesting + options: --cap-add=NET_ADMIN + env: + SUBLIME_TEXT_VERSION: ${{ matrix.st_version }} + steps: + - uses: actions/checkout@v1 + - run: sh -e /etc/init.d/xvfb start + - run: curl -OL https://raw.githubusercontent.com/SublimeText/UnitTesting/master/sbin/github.sh + - run: | + PATH="$HOME/.local/bin:$PATH" + sh github.sh bootstrap + sh github.sh install_package_control + sh github.sh run_tests diff --git a/.github/workflows/deploy-gh-pages.yml b/.github/workflows/deploy-gh-pages.yml new file mode 100644 index 00000000..e3eba1b4 --- /dev/null +++ b/.github/workflows/deploy-gh-pages.yml @@ -0,0 +1,27 @@ +name: Deploy Docs to Github Pages + +on: + push: + branches: + - 'master' + paths: + - 'docs/**' + workflow_dispatch: + +jobs: + build: + name: Deploy Docs to Github Pages + runs-on: ubuntu-18.04 + steps: + - name: Checkout Repository + uses: actions/checkout@v2 + with: + fetch-depth: 0 + - name: Set up Python + uses: actions/setup-python@v2 + with: + python-version: '3.8' + - name: Install MkDocs + run: pip install -r docs/requirements.txt + - name: Run MkDocs + run: mkdocs gh-deploy diff --git a/.gitignore b/.gitignore index 1abfd111..5dfb9eda 100644 --- a/.gitignore +++ b/.gitignore @@ -1,4 +1,15 @@ +# python cache files +__pycache__/ +.mypy_cache/ +.pytest_cache/ +.tox/ +.venv/ *.pyc + +# other folders +/site +/_warehouse + +# files *.cache MarkdownEditing.taskpaper -/_warehouse diff --git a/.python-version b/.python-version new file mode 100644 index 00000000..98fccd6d --- /dev/null +++ b/.python-version @@ -0,0 +1 @@ +3.8 \ No newline at end of file diff --git a/Bold and Italic Markers.tmPreferences b/Bold and Italic Markers.tmPreferences deleted file mode 100644 index 4927b954..00000000 --- a/Bold and Italic Markers.tmPreferences +++ /dev/null @@ -1,30 +0,0 @@ - - - - - name - Bold and Italic Markers - scope - text.html.markdown - settings - - shellVariables - - - name - MD_BOLD_MARKER - value - __ - - - name - MD_ITALIC_MARKER - value - _ - - - - uuid - E3F0F1B0-53C8-11E3-8F96-0800200C9A66 - - diff --git a/Context.sublime-menu b/Context.sublime-menu index 8c22d93b..ed8863dd 100644 --- a/Context.sublime-menu +++ b/Context.sublime-menu @@ -1,38 +1,56 @@ [ -{ - "caption": "MDE: Fold Section", - "command": "fold_section_context" -}, -{ - "caption": "MDE: Unfold Section", - "command": "unfold_section_context" -}, -{ - "caption": "MDE: Jump Reference", - "command": "reference_jump_context" -}, -{ - "caption": "MDE: Convert inline link to reference", - "command": "convert_inline_link_to_reference" -}, -{ - "caption": "MDE: Open wiki page", - "command": "open_page" -}, -{ - "caption": "MDE: Open home wiki page", - "command": "open_home_page" -}, -{ - "caption": "MDE: Open todays journal page", - "command": "open_journal" -}, -{ - "caption": "MDE: Make wiki page reference", - "command": "make_page_reference" -}, -{ - "caption": "MDE: List back links", - "command": "list_back_links" -} -] \ No newline at end of file + { + "caption": "MarkdownEditing", + "id": "markdownediting", + "children": [ + { + "caption": "-", + "id": "folding" + }, + { + "caption": "Fold Section", + "command": "mde_fold_section_context" + }, + { + "caption": "Unfold Section", + "command": "mde_unfold_section_context" + }, + { + "caption": "-", + "id": "references" + }, + { + "caption": "Jump Reference", + "command": "mde_reference_jump_context" + }, + { + "caption": "Convert inline link to reference", + "command": "mde_convert_inline_link_to_reference" + }, + { + "caption": "-", + "id": "wiki" + }, + { + "caption": "Open wiki page", + "command": "mde_open_page" + }, + { + "caption": "Open home wiki page", + "command": "mde_open_home_page" + }, + { + "caption": "Open todays journal page", + "command": "mde_open_journal" + }, + { + "caption": "Make wiki page reference", + "command": "mde_make_page_reference" + }, + { + "caption": "List back links", + "command": "mde_list_back_links" + } + ] + } +] diff --git a/Default (Linux).sublime-keymap b/Default (Linux).sublime-keymap index 9a31b70b..32fb09c1 100644 --- a/Default (Linux).sublime-keymap +++ b/Default (Linux).sublime-keymap @@ -1,699 +1,1193 @@ [ - // selection pairing with *, _ and ` - { "keys": ["*"], "command": "insert_snippet", "args": {"contents": "*$0*"}, "context": - [ - { "key": "setting.auto_match_enabled", "operator": "equal", "operand": true }, - { "key": "selection_empty", "operator": "equal", "operand": true, "match_all": true }, - { "key": "following_text", "operator": "regex_contains", "operand": "^(?:\t| |\\)|]|\\}|$)", "match_all": true }, - { "key": "preceding_text", "operator": "not_regex_contains", "operand": "['a-zA-Z0-9_*]$", "match_all": true }, - { "key": "eol_selector", "operator": "not_equal", "operand": "string.quoted.single", "match_all": true }, - { "key": "selector", "operator": "equal", "operand": "text.html.markdown", "match_all": true }, - { "key": "selector", "operator": "not_equal", "operand": "markup.raw", "match_all": true } - ] - }, - { "keys": ["*"], "command": "run_macro_file", "args": {"file": "Packages/MarkdownEditing/macros/Skip Closing Character.sublime-macro"}, "context": - [ - { "key": "selection_empty", "operator": "equal", "operand": true, "match_all": true }, - { "key": "following_text", "operator": "regex_contains", "operand": "^\\*", "match_all": true }, - { "key": "selector", "operator": "equal", "operand": "text.html.markdown", "match_all": true }, - { "key": "selector", "operator": "not_equal", "operand": "markup.raw", "match_all": true } - ] - }, - { "keys": ["*"], "command": "insert_snippet", "args": {"contents": "*${0:$SELECTION}*"}, "context": - [ - { "key": "setting.auto_match_enabled", "operator": "equal", "operand": true }, - { "key": "selection_empty", "operator": "equal", "operand": false, "match_all": true }, - { "key": "selector", "operator": "equal", "operand": "text.html.markdown", "match_all": true }, - { "key": "selector", "operator": "not_equal", "operand": "markup.raw", "match_all": true } - ] - }, - { "keys": ["backspace"], "command": "run_macro_file", "args": {"file": "Packages/Default/Delete Left Right.sublime-macro"}, "context": - [ - { "key": "setting.auto_match_enabled", "operator": "equal", "operand": true }, - { "key": "selection_empty", "operator": "equal", "operand": true, "match_all": true }, - { "key": "preceding_text", "operator": "regex_contains", "operand": "\\*$", "match_all": true }, - { "key": "following_text", "operator": "regex_contains", "operand": "^\\*", "match_all": true }, - { "key": "selector", "operator": "equal", "operand": "text.html.markdown", "match_all": true }, - { "key": "selector", "operator": "not_equal", "operand": "markup.raw", "match_all": true } - ] - }, - { "keys": [" "], "command": "run_macro_file", "args": {"file": "Packages/MarkdownEditing/macros/Start List Item.sublime-macro"}, "context": - [ - { "key": "setting.auto_match_enabled", "operator": "equal", "operand": true }, - { "key": "selection_empty", "operator": "equal", "operand": true, "match_all": true }, - { "key": "preceding_text", "operator": "regex_contains", "operand": "\\*$", "match_all": true }, - { "key": "following_text", "operator": "regex_contains", "operand": "^\\*", "match_all": true }, - { "key": "selector", "operator": "equal", "operand": "text.html.markdown", "match_all": true }, - { "key": "selector", "operator": "not_equal", "operand": "markup.raw", "match_all": true } - ] - }, - { "keys": ["tab"], "command": "run_macro_file", "args": {"file": "Packages/MarkdownEditing/macros/Start List Item Tab.sublime-macro"}, "context": - [ - { "key": "setting.auto_match_enabled", "operator": "equal", "operand": true }, - { "key": "selection_empty", "operator": "equal", "operand": true, "match_all": true }, - { "key": "preceding_text", "operator": "regex_contains", "operand": "\\*$", "match_all": true }, - { "key": "following_text", "operator": "regex_contains", "operand": "^\\*", "match_all": true }, - { "key": "selector", "operator": "equal", "operand": "text.html.markdown", "match_all": true }, - { "key": "selector", "operator": "not_equal", "operand": "markup.raw", "match_all": true } - ] - }, - { "keys": ["tab"], "command": "indent_list_item", "context": - [ - { "key": "selection_empty", "operator": "equal", "operand": true, "match_all": true }, - { "key": "preceding_text", "operator": "regex_contains", "operand": "^\\s*(>\\s*)?[*+\\-]\\s+$", "match_all": true }, - { "key": "following_text", "operator": "regex_contains", "operand": "^$", "match_all": true }, - { "key": "selector", "operator": "equal", "operand": "text.html.markdown", "match_all": true }, - { "key": "selector", "operator": "not_equal", "operand": "markup.raw", "match_all": true } - ] - }, - { "keys": ["tab"], "command": "indent_list_multiitem", "context": - [ - { "key": "selection_empty", "operator": "equal", "operand": false, "match_all": true }, - { "key": "selector", "operator": "equal", "operand": "text.html.markdown", "match_all": true }, - { "key": "selector", "operator": "equal", "operand": "markup.list", "match_all": true } - ] - }, - { "keys": ["shift+tab"], "command": "indent_list_item", "args": {"reverse": true}, "context": - [ - { "key": "selection_empty", "operator": "equal", "operand": true, "match_all": true }, - { "key": "preceding_text", "operator": "regex_contains", "operand": "^\\s*(>\\s*)?[*+\\-]\\s+$", "match_all": true }, - { "key": "following_text", "operator": "regex_contains", "operand": "^$", "match_all": true }, - { "key": "selector", "operator": "equal", "operand": "text.html.markdown", "match_all": true }, - { "key": "selector", "operator": "not_equal", "operand": "markup.raw", "match_all": true } - ] - }, - { "keys": ["shift+tab"], "command": "indent_list_multiitem", "args": {"reverse": true}, "context": - [ - { "key": "selection_empty", "operator": "equal", "operand": false, "match_all": true }, - { "key": "selector", "operator": "equal", "operand": "text.html.markdown", "match_all": true }, - { "key": "selector", "operator": "equal", "operand": "markup.list", "match_all": true } - ] - }, - { "keys": ["_"], "command": "insert_snippet", "args": {"contents": "_$0_"}, "context": - [ - { "key": "setting.auto_match_enabled", "operator": "equal", "operand": true }, - { "key": "selection_empty", "operator": "equal", "operand": true, "match_all": true }, - { "key": "following_text", "operator": "regex_contains", "operand": "^(?:\t| |\\)|]|\\}|$)", "match_all": true }, - { "key": "preceding_text", "operator": "not_regex_contains", "operand": "['a-zA-Z0-9_]$", "match_all": true }, - { "key": "eol_selector", "operator": "not_equal", "operand": "string.quoted.single", "match_all": true }, - { "key": "selector", "operator": "equal", "operand": "text.html.markdown", "match_all": true }, - { "key": "selector", "operator": "not_equal", "operand": "markup.raw", "match_all": true } - ] - }, - { "keys": ["_"], "command": "insert_snippet", "args": {"contents": "_${0:$SELECTION}_"}, "context": - [ - { "key": "setting.auto_match_enabled", "operator": "equal", "operand": true }, - { "key": "selection_empty", "operator": "equal", "operand": false, "match_all": true }, - { "key": "selector", "operator": "equal", "operand": "text.html.markdown", "match_all": true }, - { "key": "selector", "operator": "not_equal", "operand": "markup.raw", "match_all": true } - ] - }, - { "keys": ["_"], "command": "run_macro_file", "args": {"file": "Packages/MarkdownEditing/macros/Skip Closing Character.sublime-macro"}, "context": - [ - { "key": "selection_empty", "operator": "equal", "operand": true, "match_all": true }, - { "key": "following_text", "operator": "regex_contains", "operand": "^_", "match_all": true }, - { "key": "selector", "operator": "equal", "operand": "text.html.markdown", "match_all": true }, - { "key": "selector", "operator": "not_equal", "operand": "markup.raw", "match_all": true } - ] - }, - { "keys": ["backspace"], "command": "run_macro_file", "args": {"file": "Packages/Default/Delete Left Right.sublime-macro"}, "context": - [ - { "key": "setting.auto_match_enabled", "operator": "equal", "operand": true }, - { "key": "selection_empty", "operator": "equal", "operand": true, "match_all": true }, - { "key": "preceding_text", "operator": "regex_contains", "operand": "_$", "match_all": true }, - { "key": "following_text", "operator": "regex_contains", "operand": "^_", "match_all": true }, - { "key": "selector", "operator": "equal", "operand": "text.html.markdown", "match_all": true }, - { "key": "selector", "operator": "not_equal", "operand": "markup.raw", "match_all": true } - ] - }, - { "keys": [" "], "command": "run_macro_file", "args": {"file": "Packages/MarkdownEditing/macros/Start List Item.sublime-macro"}, "context": - [ - { "key": "setting.auto_match_enabled", "operator": "equal", "operand": true }, - { "key": "selection_empty", "operator": "equal", "operand": true, "match_all": true }, - { "key": "preceding_text", "operator": "regex_contains", "operand": "\\_$", "match_all": true }, - { "key": "following_text", "operator": "regex_contains", "operand": "^\\_", "match_all": true }, - { "key": "selector", "operator": "equal", "operand": "text.html.markdown", "match_all": true }, - { "key": "selector", "operator": "not_equal", "operand": "markup.raw", "match_all": true } - ] - }, - { "keys": ["`"], "command": "insert_snippet", "args": {"contents": "`$0`"}, "context": - [ - { "key": "setting.auto_match_enabled", "operator": "equal", "operand": true }, - { "key": "selection_empty", "operator": "equal", "operand": true, "match_all": true }, - { "key": "following_text", "operator": "regex_contains", "operand": "^(?:\t| |\\)|]|\\}|$)", "match_all": true }, - { "key": "preceding_text", "operator": "not_regex_contains", "operand": "['a-zA-Z0-9_`]$", "match_all": true }, - { "key": "eol_selector", "operator": "not_equal", "operand": "string.quoted.single", "match_all": true }, - { "key": "selector", "operator": "equal", "operand": "text.html.markdown", "match_all": true } - ] - }, - { "keys": ["`"], "command": "insert_snippet", "args": {"contents": "`${0:$SELECTION}`"}, "context": - [ - { "key": "setting.auto_match_enabled", "operator": "equal", "operand": true }, - { "key": "selection_empty", "operator": "equal", "operand": false, "match_all": true }, - { "key": "selector", "operator": "equal", "operand": "text.html.markdown", "match_all": true } - ] - }, - { "keys": ["`"], "command": "run_macro_file", "args": {"file": "Packages/MarkdownEditing/macros/Skip Closing Character.sublime-macro"}, "context": - [ - { "key": "selection_empty", "operator": "equal", "operand": true, "match_all": true }, - { "key": "following_text", "operator": "regex_contains", "operand": "^`", "match_all": true }, - { "key": "selector", "operator": "equal", "operand": "text.html.markdown", "match_all": true } - ] - }, - { "keys": ["~"], "command": "insert_snippet", "args": {"contents": "~~${0:$SELECTION}~~"}, "context": - [ - { "key": "setting.auto_match_enabled", "operator": "equal", "operand": true }, - { "key": "selection_empty", "operator": "equal", "operand": false, "match_all": true }, - { "key": "selector", "operator": "equal", "operand": "text.html.markdown", "match_all": true }, - { "key": "selector", "operator": "not_equal", "operand": "markup.raw", "match_all": true } - ] - }, - { "keys": ["backspace"], "command": "run_macro_file", "args": {"file": "Packages/Default/Delete Left Right.sublime-macro"}, "context": - [ - { "key": "setting.auto_match_enabled", "operator": "equal", "operand": true }, - { "key": "selection_empty", "operator": "equal", "operand": true, "match_all": true }, - { "key": "preceding_text", "operator": "regex_contains", "operand": "`$", "match_all": true }, - { "key": "following_text", "operator": "regex_contains", "operand": "^`", "match_all": true }, - { "key": "selector", "operator": "equal", "operand": "text.html.markdown", "match_all": true } - ] - }, - // Bold on Alt + B - { "keys": ["alt+b"], "command": "run_macro_file", "args": {"file": "Packages/MarkdownEditing/macros/Transform Word - Bold.sublime-macro"}, "context": - [ - { "key": "selection_empty", "operator": "equal", "operand": true, "match_all": true }, - { "key": "selector", "operator": "equal", "operand": "text.html.markdown", "match_all": true } - ] - }, - { "keys": ["alt+b"], "command": "insert_snippet", "args": {"contents": "${MD_BOLD_MARKER}$1${MD_BOLD_MARKER}"}, "context": - [ - { "key": "setting.auto_match_enabled", "operator": "equal", "operand": true }, - { "key": "selection_empty", "operator": "equal", "operand": true, "match_all": true }, - { "key": "following_text", "operator": "regex_contains", "operand": "^(?:\t| |\\)|]|\\}|$)", "match_all": true }, - { "key": "preceding_text", "operator": "not_regex_contains", "operand": "['a-zA-Z0-9_]$", "match_all": true }, - { "key": "eol_selector", "operator": "not_equal", "operand": "string.quoted.single", "match_all": true }, - { "key": "selector", "operator": "equal", "operand": "text.html.markdown", "match_all": true } - ] - }, - { "keys": ["alt+b"], "command": "insert_snippet", "args": {"contents": "${MD_BOLD_MARKER}${SELECTION/(^[\\*_]*|[\\*_]*$)//g}${MD_BOLD_MARKER}"}, "context": - [ - { "key": "setting.auto_match_enabled", "operator": "equal", "operand": true }, - { "key": "selection_empty", "operator": "equal", "operand": false, "match_all": true }, - { "key": "selector", "operator": "equal", "operand": "text.html.markdown", "match_all": true } - ] - }, - // italics on Alt + I - { "keys": ["alt+i"], "command": "run_macro_file", "args": {"file": "Packages/MarkdownEditing/macros/Transform Word - Italic.sublime-macro"}, "context": - [ - { "key": "selection_empty", "operator": "equal", "operand": true, "match_all": true }, - { "key": "selector", "operator": "equal", "operand": "text.html.markdown", "match_all": true } - ] - }, - { "keys": ["alt+i"], "command": "insert_snippet", "args": {"contents": "${MD_ITALIC_MARKER}$0${MD_ITALIC_MARKER}"}, "context": - [ - { "key": "setting.auto_match_enabled", "operator": "equal", "operand": true }, - { "key": "selection_empty", "operator": "equal", "operand": true, "match_all": true }, - { "key": "following_text", "operator": "regex_contains", "operand": "^(?:\t| |\\)|]|\\}|$)", "match_all": true }, - { "key": "preceding_text", "operator": "not_regex_contains", "operand": "['a-zA-Z0-9_]$", "match_all": true }, - { "key": "eol_selector", "operator": "not_equal", "operand": "string.quoted.single", "match_all": true }, - { "key": "selector", "operator": "equal", "operand": "text.html.markdown", "match_all": true } - ] - }, - { "keys": ["alt+i"], "command": "insert_snippet", "args": {"contents": "${MD_ITALIC_MARKER}${SELECTION/(^[\\*_]*|[\\*_]*$)//g}${MD_ITALIC_MARKER}"}, "context": - [ - { "key": "setting.auto_match_enabled", "operator": "equal", "operand": true }, - { "key": "selection_empty", "operator": "equal", "operand": false, "match_all": true }, - { "key": "selector", "operator": "equal", "operand": "text.html.markdown", "match_all": true } - ] - }, + // Fix smart expand selection + // see: https://github.com/sublimehq/sublime_text/issues/4125 + { "keys": ["ctrl+shift+a"], "command": "expand_selection", "args": {"to": "smart"}, "context": + [ + { "key": "selector", "operand": "text.html.markdown - text.html.markdown text.html - text.html.markdown text.xml - text.html.markdown meta.disable-markdown", "match_all": true } + ] + }, - // Unbold on Alt + B if already bold - { "keys": ["alt+b"], "command": "insert_snippet", "args": {"contents": "${SELECTION/(^[\\*_]{2}|[\\*_]{2}$)//g}"}, "context": - [ - { "key": "selection_empty", "operator": "equal", "operand": false, "match_all": true }, - { "key": "text", "operator": "regex_match", "operand": "^[*_]{2}.*[*_]{2}$", "match_all": true }, - { "key": "selector", "operator": "equal", "operand": "text.html.markdown", "match_all": true } - ] - }, - { "keys": ["alt+b"], "command": "run_macro_file", "args": {"file": "Packages/MarkdownEditing/macros/Transform Word - Unbold Unitalicize.sublime-macro"}, "context": - [ - { "key": "selection_empty", "operator": "equal", "operand": true, "match_all": true }, - { "key": "selector", "operator": "equal", "operand": "text.html.markdown markup.bold.markdown", "match_all": true } - ] - }, - { "keys": ["alt+b"], "command": "run_macro_file", "args": {"file": "Packages/MarkdownEditing/macros/Transform Word - Unbold Unitalicize.sublime-macro"}, "context": - [ - { "key": "selection_empty", "operator": "equal", "operand": true, "match_all": true }, - { "key": "preceding_text", "operator": "regex_contains", "operand": "\\b__+\\S+__+$", "match_all": true }, - { "key": "selector", "operator": "equal", "operand": "text.html.markdown", "match_all": true } - ] - }, + // + // Auto-Pairing Astersisks + // - // Unitalicize on Alt + I if already italic - { "keys": ["alt+i"], "command": "insert_snippet", "args": {"contents": "${SELECTION/(^[\\*_]|[\\*_]$)//g}"}, "context": - [ - { "key": "selection_empty", "operator": "equal", "operand": false, "match_all": true }, - { "key": "text", "operator": "regex_match", "operand": "^[*_].*[*_]$", "match_all": true }, - { "key": "selector", "operator": "equal", "operand": "text.html.markdown", "match_all": true } - ] - }, - { "keys": ["alt+i"], "command": "run_macro_file", "args": {"file": "Packages/MarkdownEditing/macros/Transform Word - Unbold Unitalicize.sublime-macro"}, "context": - [ - { "key": "selection_empty", "operator": "equal", "operand": true, "match_all": true }, - { "key": "selector", "operator": "equal", "operand": "text.html.markdown markup.italic.markdown", "match_all": true } - ] - }, - { "keys": ["alt+i"], "command": "run_macro_file", "args": {"file": "Packages/MarkdownEditing/macros/Transform Word - Unbold Unitalicize.sublime-macro"}, "context": - [ - { "key": "selection_empty", "operator": "equal", "operand": true, "match_all": true }, - { "key": "preceding_text", "operator": "regex_contains", "operand": "\\b_(?!_)\\S+_$", "match_all": true }, - { "key": "selector", "operator": "equal", "operand": "text.html.markdown", "match_all": true } - ] - }, + { "keys": ["*"], "command": "insert_snippet", "args": {"contents": "*$0*"}, "context": + [ + { "key": "selector", "operator": "equal", "operand": "text.html.markdown - meta.frontmatter - meta.disable-markdown - markup.raw - markup.kbd", "match_all": true }, + { "key": "setting.auto_match_enabled", "operator": "equal", "operand": true }, + { "key": "selection_empty", "operator": "equal", "operand": true, "match_all": true }, + { "key": "eol_selector", "operator": "not_equal", "operand": "string.quoted.single", "match_all": true }, + { "key": "preceding_text", "operator": "not_regex_contains", "operand": "['a-zA-Z0-9_*]$", "match_all": true }, + { "key": "following_text", "operator": "regex_contains", "operand": "^(?:\t| |\\)|]|\\}|$)", "match_all": true } + ] + }, + { "keys": ["*"], "command": "insert_snippet", "args": {"contents": "*${0:$SELECTION}*"}, "context": + [ + { "key": "selector", "operator": "equal", "operand": "text.html.markdown - meta.frontmatter - meta.disable-markdown - markup.raw - markup.kbd", "match_all": true }, + { "key": "setting.auto_match_enabled", "operator": "equal", "operand": true }, + { "key": "selection_empty", "operator": "equal", "operand": false, "match_all": true } + ] + }, + { "keys": ["*"], "command": "move", "args": {"by": "characters", "forward": true}, "context": + [ + { "key": "selector", "operator": "equal", "operand": "text.html.markdown - meta.frontmatter - meta.disable-markdown - markup.raw - markup.kbd", "match_all": true }, + { "key": "selection_empty", "operator": "equal", "operand": true, "match_all": true }, + { "key": "following_text", "operator": "regex_contains", "operand": "^\\*", "match_all": true } + ] + }, + { "keys": ["backspace"], "command": "run_macro_file", "args": {"file": "Packages/Default/Delete Left Right.sublime-macro"}, "context": + [ + { "key": "selector", "operator": "equal", "operand": "text.html.markdown - meta.frontmatter - meta.disable-markdown - markup.raw - markup.kbd", "match_all": true }, + { "key": "setting.auto_match_enabled", "operator": "equal", "operand": true }, + { "key": "selection_empty", "operator": "equal", "operand": true, "match_all": true }, + { "key": "preceding_text", "operator": "regex_contains", "operand": "\\*$", "match_all": true }, + { "key": "following_text", "operator": "regex_contains", "operand": "^\\*", "match_all": true } + ] + }, + { "keys": [" "], "command": "run_macro_file", "args": {"file": "Packages/MarkdownEditing/macros/Start List Item.sublime-macro"}, "context": + [ + { "key": "selector", "operator": "equal", "operand": "text.html.markdown - meta.frontmatter - meta.disable-markdown - markup.raw - markup.kbd", "match_all": true }, + { "key": "setting.auto_match_enabled", "operator": "equal", "operand": true }, + { "key": "selection_empty", "operator": "equal", "operand": true, "match_all": true }, + { "key": "preceding_text", "operator": "regex_contains", "operand": "\\*$", "match_all": true }, + { "key": "following_text", "operator": "regex_contains", "operand": "^\\*", "match_all": true } + ] + }, + { "keys": ["tab"], "command": "run_macro_file", "args": {"file": "Packages/MarkdownEditing/macros/Start List Item Tab.sublime-macro"}, "context": + [ + { "key": "selector", "operator": "equal", "operand": "text.html.markdown - meta.frontmatter - meta.disable-markdown - markup.raw - markup.kbd", "match_all": true }, + { "key": "setting.auto_match_enabled", "operator": "equal", "operand": true }, + { "key": "selection_empty", "operator": "equal", "operand": true, "match_all": true }, + { "key": "preceding_text", "operator": "regex_contains", "operand": "\\*$", "match_all": true }, + { "key": "following_text", "operator": "regex_contains", "operand": "^\\*", "match_all": true } + ] + }, - // Headers - { "keys": ["#"], "command": "insert_snippet", "args": {"contents": "#${0: ${SELECTION/(^ | $)//g} }#"}, "context": - [ - { "key": "selection_empty", "operator": "equal", "operand": false, "match_all": true }, - { "key": "selector", "operator": "equal", "operand": "text.html.markdown", "match_all": true }, - { "key": "preceding_text", "operator": "not_regex_contains", "operand": "#{6}", "match_all": true }, - { "key": "setting.mde.match_header_hashes", "operator": "equal", "operand": true }, - { "key": "selector", "operator": "not_equal", "operand": "markup.raw", "match_all": true } - ] - }, - { "keys": ["#"], "command": "insert_snippet", "args": {"contents": "#${0: ${SELECTION/(^ | $)//g}}"}, "context": - [ - { "key": "selection_empty", "operator": "equal", "operand": false, "match_all": true }, - { "key": "selector", "operator": "equal", "operand": "text.html.markdown", "match_all": true }, - { "key": "preceding_text", "operator": "not_regex_contains", "operand": "#{6}", "match_all": true }, - { "key": "setting.mde.match_header_hashes", "operator": "equal", "operand": false }, - { "key": "selector", "operator": "not_equal", "operand": "markup.raw", "match_all": true } - ] - }, - { "keys": ["#"], "command": "run_macro_file", "args": {"file": "Packages/MarkdownEditing/macros/Padded Headline.sublime-macro"}, "context": - [ - { "key": "selection_empty", "operator": "equal", "operand": false, "match_all": true }, - { "key": "selector", "operator": "equal", "operand": "text.html.markdown", "match_all": true }, - { "key": "preceding_text", "operator": "regex_contains", "operand": "#{6}", "match_all": true }, - { "key": "following_text", "operator": "regex_contains", "operand": "#+", "match_all": true }, - { "key": "setting.mde.match_header_hashes", "operator": "equal", "operand": true }, - { "key": "selector", "operator": "not_equal", "operand": "markup.raw", "match_all": true } - ] - }, - { "keys": ["#"], "command": "run_macro_file", "args": {"file": "Packages/MarkdownEditing/macros/Padded Headline.sublime-macro"}, "context": - [ - { "key": "selection_empty", "operator": "equal", "operand": false, "match_all": true }, - { "key": "selector", "operator": "equal", "operand": "text.html.markdown", "match_all": true }, - { "key": "preceding_text", "operator": "regex_contains", "operand": "#{6}", "match_all": true }, - { "key": "setting.mde.match_header_hashes", "operator": "equal", "operand": false }, - { "key": "selector", "operator": "not_equal", "operand": "markup.raw", "match_all": true } - ] - }, - { "keys": ["enter"], "command": "insert_snippet", "args": {"contents": " ${TM_CURRENT_LINE/(#+?)[^#].*$/$1\n/}"}, "context": - [ - { "key": "selector", "operator": "equal", "operand": "text.html.markdown", "match_all": true }, - { "key": "preceding_text", "operator": "regex_contains", "operand": "^#+\\s+[^#]", "match_all": true }, - { "key": "preceding_text", "operator": "not_regex_contains", "operand": "#+$", "match_all": true }, - { "key": "following_text", "operator": "regex_contains", "operand": "^\\s*$", "match_all": true }, - { "key": "setting.mde.match_header_hashes", "operator": "equal", "operand": true }, - { "key": "auto_complete_visible", "operator": "equal", "operand": false }, - { "key": "selector", "operator": "not_equal", "operand": "markup.raw", "match_all": true } - ] - }, - // Extend lists - { "keys": ["enter"], "command": "insert_snippet", "args": {"contents": "${TM_CURRENT_LINE/^(\\s*([*\\-+])(\\s+)).*/\n$2$3/}"}, "context": - [ - { "key": "selector", "operator": "equal", "operand": "text.html.markdown", "match_all": true }, - { "key": "preceding_text", "operator": "regex_contains", "operand": "^(\\s*([*\\-+])\\s+)\\S.*", "match_all": true }, - { "key": "auto_complete_visible", "operator": "equal", "operand": false }, - { "key": "selector", "operator": "not_equal", "operand": "markup.raw", "match_all": true } - ] - }, - // Extend lists with GFM tasks - { "keys": ["enter"], "command": "insert_snippet", "args": {"contents": "${TM_CURRENT_LINE/^(\\s*([*\\-+])(\\s+)\\[[ x]\\](\\s+)).*/\n$2$3[ ]$4/}"}, "context": - [ - { "key": "selector", "operator": "equal", "operand": "text.html.markdown", "match_all": true }, - { "key": "preceding_text", "operator": "regex_contains", "operand": "^(\\s*([*\\-+])\\s+)\\[[ x]\\]\\s+\\S.*", "match_all": true }, - { "key": "auto_complete_visible", "operator": "equal", "operand": false }, - { "key": "selector", "operator": "not_equal", "operand": "markup.raw", "match_all": true } - ] - }, - // Extend Numbered Lists - { "keys": ["enter"], "command": "number_list", "context": - [ - { "key": "selector", "operator": "equal", "operand": "text.html.markdown", "match_all": true }, - { "key": "preceding_text", "operator": "regex_contains", "operand": "^(\\s*(\\d+\\.)\\s+)\\S.*", "match_all": true }, - { "key": "auto_complete_visible", "operator": "equal", "operand": false }, - { "key": "selector", "operator": "not_equal", "operand": "markup.raw", "match_all": true } - ] - }, - // Extend Numbered Reference - { "keys": ["enter"], "command": "number_list_reference", "context": - [ - { "key": "selector", "operator": "equal", "operand": "text.html.markdown", "match_all": true }, - { "key": "preceding_text", "operator": "regex_contains", "operand": "^(\\s*\\[(\\d+)\\]:\\s*)\\S.*", "match_all": true }, - { "key": "auto_complete_visible", "operator": "equal", "operand": false }, - { "key": "selector", "operator": "not_equal", "operand": "markup.raw", "match_all": true } - ] - }, - // Remove empty list item - { "keys": ["enter"], "command": "run_macro_file", "args": {"file": "Packages/MarkdownEditing/macros/Remove Empty List Item.sublime-macro"}, "context": - [ - { "key": "selector", "operator": "equal", "operand": "text.html.markdown", "match_all": true }, - { "key": "preceding_text", "operator": "regex_contains", "operand": "^(\\s*(\\[\\d+\\]:|[*\\-+]|\\d+\\.)\\s+)$", "match_all": true }, - { "key": "following_text", "operator": "regex_contains", "operand": "^\\s*$", "match_all": true }, - { "key": "auto_complete_visible", "operator": "equal", "operand": false }, - { "key": "selector", "operator": "not_equal", "operand": "markup.raw", "match_all": true } - ] - }, - // Extend blockquote - { "keys": ["enter"], "command": "insert_snippet", "args": {"contents": "${TM_CURRENT_LINE/^(\\s*((>+\\s+)+([*\\-+]\\s+)?)).*/\n$2/}"}, "context": - [ - { "key": "selector", "operator": "equal", "operand": "text.html.markdown", "match_all": true }, - { "key": "preceding_text", "operator": "regex_contains", "operand": "^\\s*>+\\s+", "match_all": true }, - { "key": "auto_complete_visible", "operator": "equal", "operand": false } - ] - }, - // Convert to blockquote - { "keys": [">"], "command": "run_macro_file", "args": {"file": "Packages/MarkdownEditing/macros/Convert to Blockquote.sublime-macro"}, "context": - [ - { "key": "selection_empty", "operator": "equal", "operand": false, "match_all": true }, - { "key": "selector", "operator": "equal", "operand": "text.html.markdown", "match_all": true }, - { "key": "selector", "operator": "not_equal", "operand": "markup.raw", "match_all": true } - ] - }, - { "keys": ["tab"], "command": "complete_underlined_header", "context": - [ - { "key": "selector", "operator": "equal", "operand": "text.html.markdown", "match_all": true }, - { "key": "selection_empty", "operator": "equal", "operand": true, "match_all": true }, - { "key": "auto_complete_visible", "operator": "equal", "operand": false, "match_all": true }, - { "key": "preceding_text", "operator": "regex_contains", "operand": "^\\-+$|^\\=+$", "match_all": true }, - { "key": "selector", "operator": "not_equal", "operand": "markup.raw", "match_all": true } - ] - }, - // Surround with <> on URLs, regex copied from https://mathiasbynens.be/demo/url-regex, @diegoperini (502 chars) - { "keys": ["<"], "command": "insert_snippet", "args": {"contents": "<${0:$SELECTION}>"}, "context": - [ - { "key": "setting.auto_match_enabled", "operator": "equal", "operand": true }, - { "key": "selection_empty", "operator": "equal", "operand": false, "match_all": true }, - { "key": "selector", "operator": "equal", "operand": "text.html.markdown", "match_all": true }, - { "key": "text", "operator": "regex_match", "operand": "(?:(?:https?|ftp)://)(?:\\S+(?::\\S*)?@)?(?:(?!10(?:\\.\\d{1,3}){3})(?!127(?:\\.\\d{1,3}){3})(?!169\\.254(?:\\.\\d{1,3}){2})(?!192\\.168(?:\\.\\d{1,3}){2})(?!172\\.(?:1[6-9]|2\\d|3[0-1])(?:\\.\\d{1,3}){2})(?:[1-9]\\d?|1\\d\\d|2[01]\\d|22[0-3])(?:\\.(?:1?\\d{1,2}|2[0-4]\\d|25[0-5])){2}(?:\\.(?:[1-9]\\d?|1\\d\\d|2[0-4]\\d|25[0-4]))|(?:(?:[a-z\\x{00a1}-\\x{ffff}0-9]+-?)*[a-z\\x{00a1}-\\x{ffff}0-9]+)(?:\\.(?:[a-z\\x{00a1}-\\x{ffff}0-9]+-?)*[a-z\\x{00a1}-\\x{ffff}0-9]+)*(?:\\.(?:[a-z\\x{00a1}-\\x{ffff}]{2,})))(?::\\d{2,5})?(?:/[^\\s]*)?", "match_all": true } - ] - }, + // + // Auto-Pairing Underscore + // - // inline image insertion - { "keys": ["super+shift+k"], "command": "reference_new_inline_image", "context": - [ - { "key": "setting.mde.keymap_disable.reference_new_inline_image", "operator": "not_equal", "operand": true }, - { "key": "selector", "operator": "equal", "operand": "text.html.markdown", "match_all": true } - ] - }, - // modify [] pairing so that selection is removed after pairing, ready for [] or () - { "keys": ["["], "command": "insert_snippet", "args": {"contents": "[$SELECTION]$0"}, "context": - [ - { "key": "setting.auto_match_enabled", "operator": "equal", "operand": true }, - { "key": "selection_empty", "operator": "equal", "operand": false, "match_all": true }, - { "key": "selector", "operator": "equal", "operand": "text.html.markdown", "match_all": true } - ] - }, - // run paste as link command on selected text - { "keys": ["ctrl+alt+v"], "command": "reference_new_inline_link", "context": - [ - { "key": "setting.mde.keymap_disable.reference_new_inline_link", "operator": "not_equal", "operand": true }, - { "key": "selector", "operator": "equal", "operand": "text.html.markdown", "match_all": true } - ] - }, - { "keys": ["ctrl+alt+r"], "command": "reference_new_reference", "context": - [ - { "key": "setting.mde.keymap_disable.reference_new_reference", "operator": "not_equal", "operand": true }, - { "key": "selector", "operator": "equal", "operand": "text.html.markdown", "match_all": true } - ] - }, - { "keys": ["ctrl+alt+g"], "command": "reference_jump", "context": - [ - { "key": "setting.mde.keymap_disable.reference_jump", "operator": "not_equal", "operand": true }, - { "key": "selector", "operator": "equal", "operand": "text.html.markdown", "match_all": true } - ] - }, - // Set Headers Levels With Shortcuts - { "keys": ["ctrl+1"], "command": "insert_snippet", "args": {"contents": "# $0"}, "context": - [ - { "key": "setting.auto_match_enabled", "operator": "equal", "operand": true }, - { "key": "selection_empty", "operator": "equal", "operand": true, "match_all": true }, - { "key": "following_text", "operator": "regex_contains", "operand": "^(?:\t| |\\)|]|\\}|$)", "match_all": true }, - { "key": "preceding_text", "operator": "not_regex_contains", "operand": "['a-zA-Z0-9_]$", "match_all": true }, - { "key": "eol_selector", "operator": "not_equal", "operand": "string.quoted.single", "match_all": true }, - { "key": "selector", "operator": "equal", "operand": "text.html.markdown", "match_all": true } - ] - }, - { "keys": ["ctrl+1"], "command": "insert_snippet", "args": {"contents": "#${0: ${SELECTION/(^( +)?(#+)?\\s*|\\s*(#+)?( +)?$)//g}}$1"}, "context": - [ - { "key": "setting.auto_match_enabled", "operator": "equal", "operand": true }, - { "key": "setting.mde.match_header_hashes", "operator": "equal", "operand": false }, - { "key": "selection_empty", "operator": "equal", "operand": false, "match_all": true }, - { "key": "selector", "operator": "equal", "operand": "text.html.markdown", "match_all": true } - ] - }, - { "keys": ["ctrl+1"], "command": "insert_snippet", "args": {"contents": "#${0: ${SELECTION/(^( +)?(#+)?\\s*|\\s*(#+)?( +)?$)//g} }#$1"}, "context": - [ - { "key": "setting.auto_match_enabled", "operator": "equal", "operand": true }, - { "key": "setting.mde.match_header_hashes", "operator": "equal", "operand": true }, - { "key": "selection_empty", "operator": "equal", "operand": false, "match_all": true }, - { "key": "selector", "operator": "equal", "operand": "text.html.markdown", "match_all": true } - ] - }, - { "keys": ["ctrl+2"], "command": "insert_snippet", "args": {"contents": "## $0"}, "context": - [ - { "key": "setting.auto_match_enabled", "operator": "equal", "operand": true }, - { "key": "selection_empty", "operator": "equal", "operand": true, "match_all": true }, - { "key": "following_text", "operator": "regex_contains", "operand": "^(?:\t| |\\)|]|\\}|$)", "match_all": true }, - { "key": "preceding_text", "operator": "not_regex_contains", "operand": "['a-zA-Z0-9_]$", "match_all": true }, - { "key": "eol_selector", "operator": "not_equal", "operand": "string.quoted.single", "match_all": true }, - { "key": "selector", "operator": "equal", "operand": "text.html.markdown", "match_all": true } - ] - }, - { "keys": ["ctrl+2"], "command": "insert_snippet", "args": {"contents": "##${0: ${SELECTION/(^( +)?(#+)?\\s*|\\s*(#+)?( +)?$)//g}}$1"}, "context": - [ - { "key": "setting.auto_match_enabled", "operator": "equal", "operand": true }, - { "key": "setting.mde.match_header_hashes", "operator": "equal", "operand": false }, - { "key": "selection_empty", "operator": "equal", "operand": false, "match_all": true }, - { "key": "selector", "operator": "equal", "operand": "text.html.markdown", "match_all": true } - ] - }, - { "keys": ["ctrl+2"], "command": "insert_snippet", "args": {"contents": "##${0: ${SELECTION/(^( +)?(#+)?\\s*|\\s*(#+)?( +)?$)//g} }##$1"}, "context": - [ - { "key": "setting.auto_match_enabled", "operator": "equal", "operand": true }, - { "key": "setting.mde.match_header_hashes", "operator": "equal", "operand": true }, - { "key": "selection_empty", "operator": "equal", "operand": false, "match_all": true }, - { "key": "selector", "operator": "equal", "operand": "text.html.markdown", "match_all": true } - ] - }, - { "keys": ["ctrl+3"], "command": "insert_snippet", "args": {"contents": "### $0"}, "context": - [ - { "key": "setting.auto_match_enabled", "operator": "equal", "operand": true }, - { "key": "selection_empty", "operator": "equal", "operand": true, "match_all": true }, - { "key": "following_text", "operator": "regex_contains", "operand": "^(?:\t| |\\)|]|\\}|$)", "match_all": true }, - { "key": "preceding_text", "operator": "not_regex_contains", "operand": "['a-zA-Z0-9_]$", "match_all": true }, - { "key": "eol_selector", "operator": "not_equal", "operand": "string.quoted.single", "match_all": true }, - { "key": "selector", "operator": "equal", "operand": "text.html.markdown", "match_all": true } - ] - }, - { "keys": ["ctrl+3"], "command": "insert_snippet", "args": {"contents": "###${0: ${SELECTION/(^( +)?(#+)?\\s*|\\s*(#+)?( +)?$)//g}}$1"}, "context": - [ - { "key": "setting.auto_match_enabled", "operator": "equal", "operand": true }, - { "key": "setting.mde.match_header_hashes", "operator": "equal", "operand": false }, - { "key": "selection_empty", "operator": "equal", "operand": false, "match_all": true }, - { "key": "selector", "operator": "equal", "operand": "text.html.markdown", "match_all": true } - ] - }, - { "keys": ["ctrl+3"], "command": "insert_snippet", "args": {"contents": "###${0: ${SELECTION/(^( +)?(#+)?\\s*|\\s*(#+)?( +)?$)//g} }###$1"}, "context": - [ - { "key": "setting.auto_match_enabled", "operator": "equal", "operand": true }, - { "key": "setting.mde.match_header_hashes", "operator": "equal", "operand": true }, - { "key": "selection_empty", "operator": "equal", "operand": false, "match_all": true }, - { "key": "selector", "operator": "equal", "operand": "text.html.markdown", "match_all": true } - ] - }, - { "keys": ["ctrl+4"], "command": "insert_snippet", "args": {"contents": "#### $0"}, "context": - [ - { "key": "setting.auto_match_enabled", "operator": "equal", "operand": true }, - { "key": "selection_empty", "operator": "equal", "operand": true, "match_all": true }, - { "key": "following_text", "operator": "regex_contains", "operand": "^(?:\t| |\\)|]|\\}|$)", "match_all": true }, - { "key": "preceding_text", "operator": "not_regex_contains", "operand": "['a-zA-Z0-9_]$", "match_all": true }, - { "key": "eol_selector", "operator": "not_equal", "operand": "string.quoted.single", "match_all": true }, - { "key": "selector", "operator": "equal", "operand": "text.html.markdown", "match_all": true } - ] - }, - { "keys": ["ctrl+4"], "command": "insert_snippet", "args": {"contents": "####${0: ${SELECTION/(^( +)?(#+)?\\s*|\\s*(#+)?( +)?$)//g}}$1"}, "context": - [ - { "key": "setting.auto_match_enabled", "operator": "equal", "operand": true }, - { "key": "setting.mde.match_header_hashes", "operator": "equal", "operand": false }, - { "key": "selection_empty", "operator": "equal", "operand": false, "match_all": true }, - { "key": "selector", "operator": "equal", "operand": "text.html.markdown", "match_all": true } - ] - }, - { "keys": ["ctrl+4"], "command": "insert_snippet", "args": {"contents": "####${0: ${SELECTION/(^( +)?(#+)?\\s*|\\s*(#+)?( +)?$)//g} }####$1"}, "context": - [ - { "key": "setting.auto_match_enabled", "operator": "equal", "operand": true }, - { "key": "setting.mde.match_header_hashes", "operator": "equal", "operand": true }, - { "key": "selection_empty", "operator": "equal", "operand": false, "match_all": true }, - { "key": "selector", "operator": "equal", "operand": "text.html.markdown", "match_all": true } - ] - }, - { "keys": ["ctrl+5"], "command": "insert_snippet", "args": {"contents": "##### $0"}, "context": - [ - { "key": "setting.auto_match_enabled", "operator": "equal", "operand": true }, - { "key": "selection_empty", "operator": "equal", "operand": true, "match_all": true }, - { "key": "following_text", "operator": "regex_contains", "operand": "^(?:\t| |\\)|]|\\}|$)", "match_all": true }, - { "key": "preceding_text", "operator": "not_regex_contains", "operand": "['a-zA-Z0-9_]$", "match_all": true }, - { "key": "eol_selector", "operator": "not_equal", "operand": "string.quoted.single", "match_all": true }, - { "key": "selector", "operator": "equal", "operand": "text.html.markdown", "match_all": true } - ] - }, - { "keys": ["ctrl+5"], "command": "insert_snippet", "args": {"contents": "#####${0: ${SELECTION/(^( +)?(#+)?\\s*|\\s*(#+)?( +)?$)//g}}$1"}, "context": - [ - { "key": "setting.auto_match_enabled", "operator": "equal", "operand": true }, - { "key": "setting.mde.match_header_hashes", "operator": "equal", "operand": false }, - { "key": "selection_empty", "operator": "equal", "operand": false, "match_all": true }, - { "key": "selector", "operator": "equal", "operand": "text.html.markdown", "match_all": true } - ] - }, - { "keys": ["ctrl+5"], "command": "insert_snippet", "args": {"contents": "#####${0: ${SELECTION/(^( +)?(#+)?\\s*|\\s*(#+)?( +)?$)//g} }#####$1"}, "context": - [ - { "key": "setting.auto_match_enabled", "operator": "equal", "operand": true }, - { "key": "setting.mde.match_header_hashes", "operator": "equal", "operand": true }, - { "key": "selection_empty", "operator": "equal", "operand": false, "match_all": true }, - { "key": "selector", "operator": "equal", "operand": "text.html.markdown", "match_all": true } - ] - }, - { "keys": ["ctrl+6"], "command": "insert_snippet", "args": {"contents": "###### $0"}, "context": - [ - { "key": "setting.auto_match_enabled", "operator": "equal", "operand": true }, - { "key": "selection_empty", "operator": "equal", "operand": true, "match_all": true }, - { "key": "following_text", "operator": "regex_contains", "operand": "^(?:\t| |\\)|]|\\}|$)", "match_all": true }, - { "key": "preceding_text", "operator": "not_regex_contains", "operand": "['a-zA-Z0-9_]$", "match_all": true }, - { "key": "eol_selector", "operator": "not_equal", "operand": "string.quoted.single", "match_all": true }, - { "key": "selector", "operator": "equal", "operand": "text.html.markdown", "match_all": true } - ] - }, - { "keys": ["ctrl+6"], "command": "insert_snippet", "args": {"contents": "######${0: ${SELECTION/(^( +)?(#+)?\\s*|\\s*(#+)?( +)?$)//g}}$1"}, "context": - [ - { "key": "setting.auto_match_enabled", "operator": "equal", "operand": true }, - { "key": "setting.mde.match_header_hashes", "operator": "equal", "operand": false }, - { "key": "selection_empty", "operator": "equal", "operand": false, "match_all": true }, - { "key": "selector", "operator": "equal", "operand": "text.html.markdown", "match_all": true } - ] - }, - { "keys": ["ctrl+6"], "command": "insert_snippet", "args": {"contents": "######${0: ${SELECTION/(^( +)?(#+)?\\s*|\\s*(#+)?( +)?$)//g} }######$1"}, "context": - [ - { "key": "setting.auto_match_enabled", "operator": "equal", "operand": true }, - { "key": "setting.mde.match_header_hashes", "operator": "equal", "operand": true }, - { "key": "selection_empty", "operator": "equal", "operand": false, "match_all": true }, - { "key": "selector", "operator": "equal", "operand": "text.html.markdown", "match_all": true } - ] - }, - { "keys": ["alt+shift+6"], "command": "reference_new_footnote", "context": - [ - { "key": "setting.mde.keymap_disable.reference_new_footnote", "operator": "not_equal", "operand": true }, - { "key": "selector", "operator": "equal", "operand": "text.html.markdown", "match_all": true } - ] - }, - { "keys": ["ctrl+shift+."], "command": "indent_quote", "context": - [ - { "key": "selector", "operator": "equal", "operand": "text.html.markdown", "match_all": true } - ] - }, - { "keys": ["ctrl+shift+,"], "command": "deindent_quote", "context": - [ - { "key": "selector", "operator": "equal", "operand": "text.html.markdown", "match_all": true }, - { "key": "preceding_text", "operator": "regex_contains", "operand": "(> )+", "match_all": true } - ] - }, - { "keys": ["shift+tab"], "command": "fold_section", "context": - [ - { "key": "setting.mde.keymap_disable.fold_section", "operator": "not_equal", "operand": true }, - { "key": "selection_empty", "operator": "equal", "operand": true, "match_all": true }, - { "key": "preceding_text", "operator": "not_regex_match", "operand": "^\\s+", "match_all": true }, - { "key": "following_text", "operator": "not_regex_match", "operand": "^$", "match_all": true }, - { "key": "selector", "operator": "equal", "operand": "text.html.markdown", "match_all": true } - ] - }, - { "keys": ["shift+tab"], "command": "fold_section", "context": - [ - { "key": "setting.mde.keymap_disable.fold_section", "operator": "not_equal", "operand": true }, - { "key": "selection_empty", "operator": "equal", "operand": true, "match_all": true }, - { "key": "preceding_text", "operator": "not_regex_match", "operand": "^\\s+", "match_all": true }, - { "key": "selector", "operator": "not_equal", "operand": "markup.list", "match_all": true }, - { "key": "selector", "operator": "equal", "operand": "text.html.markdown", "match_all": true } - ] - }, - { "keys": ["shift+tab"], "command": "fold_section", "context": - [ - { "key": "setting.mde.keymap_disable.fold_section", "operator": "not_equal", "operand": true }, - { "key": "selection_empty", "operator": "equal", "operand": false, "match_all": true }, - { "key": "text", "operator": "regex_contains", "operand": "^(#{1,6}(?!#))|^(-{3,}|={3,})$"}, - { "key": "selector", "operator": "equal", "operand": "text.html.markdown", "match_all": true } - ] - }, - { "keys": ["ctrl+shift+tab"], "command": "show_fold_all_sections", "context": - [ - { "key": "setting.mde.keymap_disable.show_fold_all_sections", "operator": "not_equal", "operand": true }, - { "key": "selector", "operator": "equal", "operand": "text.html.markdown", "match_all": true } - ] - }, - { "keys": ["ctrl+shift+alt+pageup"], "command": "goto_previous_heading", "args": {"same_level": true}, "context": - [ - { "key": "setting.mde.keymap_disable.goto_previous_heading", "operator": "not_equal", "operand": true }, - { "key": "selector", "operator": "equal", "operand": "text.html.markdown", "match_all": true } - ] - }, - { "keys": ["ctrl+shift+alt+pagedown"], "command": "goto_next_heading", "args": {"same_level": true}, "context": - [ - { "key": "setting.mde.keymap_disable.goto_next_heading", "operator": "not_equal", "operand": true }, - { "key": "selector", "operator": "equal", "operand": "text.html.markdown", "match_all": true } - ] - }, - { "keys": ["ctrl+shift+pageup"], "command": "goto_previous_heading", "args": {"same_level": false}, "context": - [ - { "key": "setting.mde.keymap_disable.goto_previous_heading", "operator": "not_equal", "operand": true }, - { "key": "selector", "operator": "equal", "operand": "text.html.markdown", "match_all": true } - ] - }, - { "keys": ["ctrl+shift+pagedown"], "command": "goto_next_heading", "args": {"same_level": false}, "context": - [ - { "key": "setting.mde.keymap_disable.goto_next_heading", "operator": "not_equal", "operand": true }, - { "key": "selector", "operator": "equal", "operand": "text.html.markdown", "match_all": true } - ] - }, - {"keys": ["ctrl+alt+h"], "command": "open_home_page", "context": - [ - { "key": "setting.mde.keymap_disable.open_home_page", "operator": "not_equal", "operand": true }, - { "key": "selector", "operator": "equal", "operand": "text.html.markdown", "match_all": true } - ] - }, - {"keys": ["ctrl+alt+d"], "command": "open_page", "context": - [ - { "key": "setting.mde.keymap_disable.open_page", "operator": "not_equal", "operand": true }, - { "key": "selector", "operator": "equal", "operand": "meta.link.wiki.markdown", "match_all": true } - ] - }, - {"keys": ["ctrl+alt+d"], "command": "make_page_reference", "context": - [ - { "key": "setting.mde.keymap_disable.make_page_reference", "operator": "not_equal", "operand": true }, - { "key": "selector", "operator": "equal", "operand": "text.html.markdown", "match_all": true }, - { "key": "selector", "operator": "not_equal", "operand": "meta.link.wiki.markdown", "match_all": true }, - { "key": "selector", "operator": "not_equal", "operand": "markup.underline.link.markdown", "match_all": true } - ] - }, - {"keys": ["ctrl+alt+x"], "command": "list_back_links", "context": - [ - { "key": "setting.mde.keymap_disable.list_back_links", "operator": "not_equal", "operand": true }, - { "key": "selector", "operator": "equal", "operand": "text.html.markdown", "match_all": true } - ] - }, - {"keys": ["ctrl+alt+j"], "command": "open_journal", "context": - [ - { "key": "setting.mde.keymap_disable.open_journal", "operator": "not_equal", "operand": true }, - { "key": "selector", "operator": "equal", "operand": "text.html.markdown", "match_all": true } - ] - } + { "keys": ["_"], "command": "insert_snippet", "args": {"contents": "_$0_"}, "context": + [ + { "key": "selector", "operator": "equal", "operand": "text.html.markdown - meta.frontmatter - meta.disable-markdown - markup.raw - markup.kbd", "match_all": true }, + { "key": "setting.auto_match_enabled", "operator": "equal", "operand": true }, + { "key": "selection_empty", "operator": "equal", "operand": true, "match_all": true }, + { "key": "eol_selector", "operator": "not_equal", "operand": "string.quoted.single", "match_all": true }, + { "key": "preceding_text", "operator": "not_regex_contains", "operand": "['a-zA-Z0-9_]$", "match_all": true }, + { "key": "following_text", "operator": "regex_contains", "operand": "^(?:\t| |\\)|]|\\}|$)", "match_all": true } + ] + }, + { "keys": ["_"], "command": "insert_snippet", "args": {"contents": "_${0:$SELECTION}_"}, "context": + [ + { "key": "selector", "operator": "equal", "operand": "text.html.markdown - meta.frontmatter - meta.disable-markdown - markup.raw - markup.kbd", "match_all": true }, + { "key": "setting.auto_match_enabled", "operator": "equal", "operand": true }, + { "key": "selection_empty", "operator": "equal", "operand": false, "match_all": true } + ] + }, + { "keys": ["_"], "command": "move", "args": {"by": "characters", "forward": true}, "context": + [ + { "key": "selector", "operator": "equal", "operand": "text.html.markdown - meta.frontmatter - meta.disable-markdown - markup.raw - markup.kbd", "match_all": true }, + { "key": "selection_empty", "operator": "equal", "operand": true, "match_all": true }, + { "key": "following_text", "operator": "regex_contains", "operand": "^_", "match_all": true } + ] + }, + { "keys": ["backspace"], "command": "run_macro_file", "args": {"file": "Packages/Default/Delete Left Right.sublime-macro"}, "context": + [ + { "key": "selector", "operator": "equal", "operand": "text.html.markdown - meta.frontmatter - meta.disable-markdown - markup.raw - markup.kbd", "match_all": true }, + { "key": "setting.auto_match_enabled", "operator": "equal", "operand": true }, + { "key": "selection_empty", "operator": "equal", "operand": true, "match_all": true }, + { "key": "preceding_text", "operator": "regex_contains", "operand": "_$", "match_all": true }, + { "key": "following_text", "operator": "regex_contains", "operand": "^_", "match_all": true } + ] + }, + { "keys": [" "], "command": "run_macro_file", "args": {"file": "Packages/MarkdownEditing/macros/Start List Item.sublime-macro"}, "context": + [ + { "key": "selector", "operator": "equal", "operand": "text.html.markdown - meta.frontmatter - meta.disable-markdown - markup.raw - markup.kbd", "match_all": true }, + { "key": "setting.auto_match_enabled", "operator": "equal", "operand": true }, + { "key": "selection_empty", "operator": "equal", "operand": true, "match_all": true }, + { "key": "preceding_text", "operator": "regex_contains", "operand": "\\_$", "match_all": true }, + { "key": "following_text", "operator": "regex_contains", "operand": "^\\_", "match_all": true } + ] + }, + { "keys": ["tab"], "command": "run_macro_file", "args": {"file": "Packages/MarkdownEditing/macros/Start List Item Tab.sublime-macro"}, "context": + [ + { "key": "selector", "operator": "equal", "operand": "text.html.markdown - meta.frontmatter - meta.disable-markdown - markup.raw - markup.kbd", "match_all": true }, + { "key": "setting.auto_match_enabled", "operator": "equal", "operand": true }, + { "key": "selection_empty", "operator": "equal", "operand": true, "match_all": true }, + { "key": "preceding_text", "operator": "regex_contains", "operand": "\\_$", "match_all": true }, + { "key": "following_text", "operator": "regex_contains", "operand": "^\\_", "match_all": true } + ] + }, + + // + // Auto-Pairing Inline Code + // + + { "keys": ["`"], "command": "insert_snippet", "args": {"contents": "`$0`"}, "context": + [ + { "key": "selector", "operator": "equal", "operand": "text.html.markdown - meta.frontmatter - meta.disable-markdown - markup.raw - markup.kbd", "match_all": true }, + { "key": "setting.auto_match_enabled", "operator": "equal", "operand": true }, + { "key": "selection_empty", "operator": "equal", "operand": true, "match_all": true }, + { "key": "preceding_text", "operator": "not_regex_contains", "operand": "[\\w`]$", "match_all": true }, + { "key": "following_text", "operator": "regex_contains", "operand": "^(?:\t| |\\)|]|\\}|\\.|,|$)", "match_all": true } + ] + }, + { "keys": ["`"], "command": "insert_snippet", "args": {"contents": "`${0:$SELECTION}`"}, "context": + [ + { "key": "selector", "operator": "equal", "operand": "text.html.markdown - meta.frontmatter - meta.disable-markdown - markup.raw - markup.kbd", "match_all": true }, + { "key": "setting.auto_match_enabled", "operator": "equal", "operand": true }, + { "key": "selection_empty", "operator": "equal", "operand": false, "match_all": true } + ] + }, + { "keys": ["`"], "command": "move", "args": {"by": "characters", "forward": true}, "context": + [ + { "key": "selector", "operator": "equal", "operand": "text.html.markdown - meta.frontmatter - meta.disable-markdown - markup.raw - markup.kbd", "match_all": true }, + { "key": "selection_empty", "operator": "equal", "operand": true, "match_all": true }, + { "key": "following_text", "operator": "regex_contains", "operand": "^`", "match_all": true } + ] + }, + { "keys": ["backspace"], "command": "run_macro_file", "args": {"file": "Packages/Default/Delete Left Right.sublime-macro"}, "context": + [ + { "key": "selector", "operator": "equal", "operand": "text.html.markdown - meta.frontmatter - meta.disable-markdown - markup.raw - markup.kbd", "match_all": true }, + { "key": "setting.auto_match_enabled", "operator": "equal", "operand": true }, + { "key": "selection_empty", "operator": "equal", "operand": true, "match_all": true }, + { "key": "preceding_text", "operator": "regex_contains", "operand": "`$", "match_all": true }, + { "key": "following_text", "operator": "regex_contains", "operand": "^`", "match_all": true } + ] + }, + + // + // Auto-Pairing Strike Through + // + + { "keys": ["~"], "command": "insert_snippet", "args": {"contents": "~~${0:$SELECTION}~~"}, "context": + [ + { "key": "selector", "operator": "equal", "operand": "text.html.markdown - meta.frontmatter - meta.disable-markdown - markup.raw - markup.kbd", "match_all": true }, + { "key": "setting.auto_match_enabled", "operator": "equal", "operand": true }, + { "key": "selection_empty", "operator": "equal", "operand": false, "match_all": true } + ] + }, + { "keys": ["backspace"], "command": "run_macro_file", "args": {"file": "Packages/MarkdownEditing/macros/Delete Left Right 2.sublime-macro"}, "context": + [ + { "key": "selector", "operator": "equal", "operand": "text.html.markdown - meta.frontmatter - meta.disable-markdown - markup.raw - markup.kbd", "match_all": true }, + { "key": "setting.auto_match_enabled", "operator": "equal", "operand": true }, + { "key": "selection_empty", "operator": "equal", "operand": true, "match_all": true }, + { "key": "preceding_text", "operator": "regex_contains", "operand": "~~$", "match_all": true }, + { "key": "following_text", "operator": "regex_contains", "operand": "^~~", "match_all": true } + ] + }, + + // + // Text Formatting Bold + // + + // auto-pair if not within a word + { "keys": ["alt+b"], "command": "insert_snippet", "args": {"contents": "**$0**"}, "context": + [ + { "key": "selector", "operator": "equal", "operand": "text.html.markdown - meta.frontmatter - meta.disable-markdown - markup.raw - markup.kbd - markup.bold - markup.bold_italic", "match_all": true }, + { "key": "setting.mde.bold_marker_asterisk", "operator": "equal", "operand": true }, + { "key": "selection_empty", "operator": "equal", "operand": true, "match_all": true }, + { "key": "eol_selector", "operator": "not_equal", "operand": "string.quoted.single", "match_all": true }, + { "key": "preceding_text", "operator": "not_regex_contains", "operand": "['a-zA-Z0-9_*]$", "match_all": true }, + { "key": "following_text", "operator": "regex_contains", "operand": "^(?:\t| |\\)|]|\\}|$)", "match_all": true } + ] + }, + { "keys": ["alt+b"], "command": "insert_snippet", "args": {"contents": "__$0__"}, "context": + [ + { "key": "selector", "operator": "equal", "operand": "text.html.markdown - meta.frontmatter - meta.disable-markdown - markup.raw - markup.kbd - markup.bold - markup.bold_italic", "match_all": true }, + { "key": "setting.mde.bold_marker_asterisk", "operator": "equal", "operand": false }, + { "key": "selection_empty", "operator": "equal", "operand": true, "match_all": true }, + { "key": "eol_selector", "operator": "not_equal", "operand": "string.quoted.single", "match_all": true }, + { "key": "preceding_text", "operator": "not_regex_contains", "operand": "['a-zA-Z0-9_*]$", "match_all": true }, + { "key": "following_text", "operator": "regex_contains", "operand": "^(?:\t| |\\)|]|\\}|$)", "match_all": true } + ] + }, + // Transform a word to bold if caret is at the beginning, in the middle of or at the end of a word + { "keys": ["alt+b"], "command": "run_macro_file", "args": {"file": "Packages/MarkdownEditing/macros/Transform Word - Bold (Asterisk).sublime-macro"}, "context": + [ + { "key": "selector", "operator": "equal", "operand": "text.html.markdown - meta.frontmatter - meta.disable-markdown - markup.raw - markup.kbd - markup.bold - markup.bold_italic", "match_all": true }, + { "key": "setting.mde.bold_marker_asterisk", "operator": "equal", "operand": true }, + { "key": "selection_empty", "operator": "equal", "operand": true, "match_all": true }, + { "key": "preceding_text", "operator": "regex_contains", "operand": "\\w$", "match_all": true } + ] + }, + { "keys": ["alt+b"], "command": "run_macro_file", "args": {"file": "Packages/MarkdownEditing/macros/Transform Word - Bold (Asterisk).sublime-macro"}, "context": + [ + { "key": "selector", "operator": "equal", "operand": "text.html.markdown - meta.frontmatter - meta.disable-markdown - markup.raw - markup.kbd - markup.bold - markup.bold_italic", "match_all": true }, + { "key": "setting.mde.bold_marker_asterisk", "operator": "equal", "operand": true }, + { "key": "selection_empty", "operator": "equal", "operand": true, "match_all": true }, + { "key": "following_text", "operator": "regex_contains", "operand": "^\\w", "match_all": true } + ] + }, + { "keys": ["alt+b"], "command": "run_macro_file", "args": {"file": "Packages/MarkdownEditing/macros/Transform Word - Bold (Underscore).sublime-macro"}, "context": + [ + { "key": "selector", "operator": "equal", "operand": "text.html.markdown - meta.frontmatter - meta.disable-markdown - markup.raw - markup.kbd - markup.bold - markup.bold_italic", "match_all": true }, + { "key": "setting.mde.bold_marker_asterisk", "operator": "equal", "operand": false }, + { "key": "selection_empty", "operator": "equal", "operand": true, "match_all": true }, + { "key": "preceding_text", "operator": "regex_contains", "operand": "\\w$", "match_all": true } + ] + }, + { "keys": ["alt+b"], "command": "run_macro_file", "args": {"file": "Packages/MarkdownEditing/macros/Transform Word - Bold (Underscore).sublime-macro"}, "context": + [ + { "key": "selector", "operator": "equal", "operand": "text.html.markdown - meta.frontmatter - meta.disable-markdown - markup.raw - markup.kbd - markup.bold - markup.bold_italic", "match_all": true }, + { "key": "setting.mde.bold_marker_asterisk", "operator": "equal", "operand": false }, + { "key": "selection_empty", "operator": "equal", "operand": true, "match_all": true }, + { "key": "following_text", "operator": "regex_contains", "operand": "^\\w", "match_all": true } + ] + }, + // Transform selection to bold + { "keys": ["alt+b"], "command": "insert_snippet", "args": {"contents": "**${SELECTION/^\\*\\*|^__|\\*\\*$|__$//g}**"}, "context": + [ + { "key": "selector", "operator": "equal", "operand": "text.html.markdown - meta.frontmatter - meta.disable-markdown - markup.raw - markup.kbd - markup.bold - markup.bold_italic", "match_all": true }, + { "key": "setting.mde.bold_marker_asterisk", "operator": "equal", "operand": true }, + { "key": "selection_empty", "operator": "equal", "operand": false, "match_all": true }, + { "key": "preceding_text", "operator": "not_regex_contains", "operand": "\\*$|__$", "match_all": true }, + { "key": "following_text", "operator": "not_regex_contains", "operand": "^\\*|^__", "match_all": true } + ] + }, + { "keys": ["alt+b"], "command": "insert_snippet", "args": {"contents": "__${SELECTION/^\\*\\*|^__|\\*\\*$|__$//g}__"}, "context": + [ + { "key": "selector", "operator": "equal", "operand": "text.html.markdown - meta.frontmatter - meta.disable-markdown - markup.raw - markup.kbd - markup.bold - markup.bold_italic", "match_all": true }, + { "key": "setting.mde.bold_marker_asterisk", "operator": "equal", "operand": false }, + { "key": "selection_empty", "operator": "equal", "operand": false, "match_all": true }, + { "key": "preceding_text", "operator": "not_regex_contains", "operand": "\\*$|__$", "match_all": true }, + { "key": "following_text", "operator": "not_regex_contains", "operand": "^\\*|^__", "match_all": true } + ] + }, + // Unbold bold text + { "keys": ["alt+b"], "command": "run_macro_file", "args": {"file": "Packages/MarkdownEditing/macros/Transform Word - Unbold.sublime-macro"}, "context": + [ + { "key": "selector", "operator": "equal", "operand": "text.html.markdown markup.bold - punctuation, text.html.markdown markup.bold_italic - punctuation", "match_all": true } + ] + }, + + // + // Text Formatting Italic + // + + // auto-pair if not within a word + { "keys": ["alt+i"], "command": "insert_snippet", "args": {"contents": "*$0*"}, "context": + [ + { "key": "selector", "operator": "equal", "operand": "text.html.markdown - meta.frontmatter - meta.disable-markdown - markup.raw - markup.kbd - markup.italic - markup.bold_italic", "match_all": true }, + { "key": "setting.mde.italic_marker_asterisk", "operator": "equal", "operand": true }, + { "key": "selection_empty", "operator": "equal", "operand": true, "match_all": true }, + { "key": "eol_selector", "operator": "not_equal", "operand": "string.quoted.single", "match_all": true }, + { "key": "preceding_text", "operator": "not_regex_contains", "operand": "['a-zA-Z0-9_*]$", "match_all": true }, + { "key": "following_text", "operator": "regex_contains", "operand": "^(?:\t| |\\)|]|\\}|$)", "match_all": true } + ] + }, + { "keys": ["alt+i"], "command": "insert_snippet", "args": {"contents": "_$0_"}, "context": + [ + { "key": "selector", "operator": "equal", "operand": "text.html.markdown - meta.frontmatter - meta.disable-markdown - markup.raw - markup.kbd - markup.italic - markup.bold_italic", "match_all": true }, + { "key": "setting.mde.italic_marker_asterisk", "operator": "equal", "operand": false }, + { "key": "selection_empty", "operator": "equal", "operand": true, "match_all": true }, + { "key": "eol_selector", "operator": "not_equal", "operand": "string.quoted.single", "match_all": true }, + { "key": "preceding_text", "operator": "not_regex_contains", "operand": "['a-zA-Z0-9_*]$", "match_all": true }, + { "key": "following_text", "operator": "regex_contains", "operand": "^(?:\t| |\\)|]|\\}|$)", "match_all": true } + ] + }, + // Transform a word to bold if caret is at the beginning, in the middle of or at the end of a word + { "keys": ["alt+i"], "command": "run_macro_file", "args": {"file": "Packages/MarkdownEditing/macros/Transform Word - Italic (Asterisk).sublime-macro"}, "context": + [ + { "key": "selector", "operator": "equal", "operand": "text.html.markdown - meta.frontmatter - meta.disable-markdown - markup.raw - markup.kbd - markup.italic - markup.bold_italic", "match_all": true }, + { "key": "setting.mde.italic_marker_asterisk", "operator": "equal", "operand": true }, + { "key": "selection_empty", "operator": "equal", "operand": true, "match_all": true }, + { "key": "preceding_text", "operator": "regex_contains", "operand": "\\w$", "match_all": true } + ] + }, + { "keys": ["alt+i"], "command": "run_macro_file", "args": {"file": "Packages/MarkdownEditing/macros/Transform Word - Italic (Asterisk).sublime-macro"}, "context": + [ + { "key": "selector", "operator": "equal", "operand": "text.html.markdown - meta.frontmatter - meta.disable-markdown - markup.raw - markup.kbd - markup.italic - markup.bold_italic", "match_all": true }, + { "key": "setting.mde.italic_marker_asterisk", "operator": "equal", "operand": true }, + { "key": "selection_empty", "operator": "equal", "operand": true, "match_all": true }, + { "key": "following_text", "operator": "regex_contains", "operand": "^\\w", "match_all": true } + ] + }, + { "keys": ["alt+i"], "command": "run_macro_file", "args": {"file": "Packages/MarkdownEditing/macros/Transform Word - Italic (Underscore).sublime-macro"}, "context": + [ + { "key": "selector", "operator": "equal", "operand": "text.html.markdown - meta.frontmatter - meta.disable-markdown - markup.raw - markup.kbd - markup.italic - markup.bold_italic", "match_all": true }, + { "key": "setting.mde.italic_marker_asterisk", "operator": "equal", "operand": false }, + { "key": "selection_empty", "operator": "equal", "operand": true, "match_all": true }, + { "key": "preceding_text", "operator": "regex_contains", "operand": "\\w$", "match_all": true } + ] + }, + { "keys": ["alt+i"], "command": "run_macro_file", "args": {"file": "Packages/MarkdownEditing/macros/Transform Word - Italic (Underscore).sublime-macro"}, "context": + [ + { "key": "selector", "operator": "equal", "operand": "text.html.markdown - meta.frontmatter - meta.disable-markdown - markup.raw - markup.kbd - markup.italic - markup.bold_italic", "match_all": true }, + { "key": "setting.mde.italic_marker_asterisk", "operator": "equal", "operand": false }, + { "key": "selection_empty", "operator": "equal", "operand": true, "match_all": true }, + { "key": "following_text", "operator": "regex_contains", "operand": "^\\w", "match_all": true } + ] + }, + // Transform selection to italics + { "keys": ["alt+i"], "command": "insert_snippet", "args": {"contents": "*${SELECTION/(^[\\*_]*|[\\*_]*$)//g}*"}, "context": + [ + { "key": "selector", "operator": "equal", "operand": "text.html.markdown - meta.frontmatter - meta.disable-markdown - markup.raw - markup.kbd - markup.italic - markup.bold_italic", "match_all": true }, + { "key": "setting.mde.italic_marker_asterisk", "operator": "equal", "operand": true }, + { "key": "selection_empty", "operator": "equal", "operand": false, "match_all": true }, + { "key": "preceding_text", "operator": "not_regex_contains", "operand": "\\*$|_$", "match_all": true }, + { "key": "following_text", "operator": "not_regex_contains", "operand": "^\\*|^_", "match_all": true } + ] + }, + // Remove italics style from text + { "keys": ["alt+i"], "command": "insert_snippet", "args": {"contents": "_${SELECTION/(^[\\*_]*|[\\*_]*$)//g}_"}, "context": + [ + { "key": "selector", "operator": "equal", "operand": "text.html.markdown - meta.frontmatter - meta.disable-markdown - markup.raw - markup.kbd - markup.italic - markup.bold_italic", "match_all": true }, + { "key": "setting.mde.italic_marker_asterisk", "operator": "equal", "operand": false }, + { "key": "selection_empty", "operator": "equal", "operand": false, "match_all": true }, + { "key": "preceding_text", "operator": "not_regex_contains", "operand": "\\*$|_$", "match_all": true }, + { "key": "following_text", "operator": "not_regex_contains", "operand": "^\\*|^_", "match_all": true } + ] + }, + { "keys": ["alt+i"], "command": "run_macro_file", "args": {"file": "Packages/MarkdownEditing/macros/Transform Word - Unitalicize.sublime-macro"}, "context": + [ + { "key": "selector", "operator": "equal", "operand": "text.html.markdown markup.italic - punctuation, text.html.markdown markup.bold_italic - punctuation", "match_all": true } + ] + }, + + // + // Headings + // + + { "keys": ["ctrl+alt+keypad0"], "command": "mde_change_headings_level", "args": {"to": 0}, "context": + [ + { "key": "selector", "operator": "equal", "operand": "text.html.markdown - meta.frontmatter - meta.disable-markdown - markup.raw", "match_all": true } + ] + }, + { "keys": ["ctrl+alt+0"], "command": "mde_change_headings_level", "args": {"to": 0}, "context": + [ + { "key": "selector", "operator": "equal", "operand": "text.html.markdown - meta.frontmatter - meta.disable-markdown - markup.raw", "match_all": true } + ] + }, + { "keys": ["ctrl+alt+keypad1"], "command": "mde_change_headings_level", "args": {"to": 1}, "context": + [ + { "key": "selector", "operator": "equal", "operand": "text.html.markdown - meta.frontmatter - meta.disable-markdown - markup.raw", "match_all": true } + ] + }, + { "keys": ["ctrl+alt+1"], "command": "mde_change_headings_level", "args": {"to": 1}, "context": + [ + { "key": "selector", "operator": "equal", "operand": "text.html.markdown - meta.frontmatter - meta.disable-markdown - markup.raw", "match_all": true } + ] + }, + { "keys": ["ctrl+alt+keypad2"], "command": "mde_change_headings_level", "args": {"to": 2}, "context": + [ + { "key": "selector", "operator": "equal", "operand": "text.html.markdown - meta.frontmatter - meta.disable-markdown - markup.raw", "match_all": true } + ] + }, + { "keys": ["ctrl+alt+2"], "command": "mde_change_headings_level", "args": {"to": 2}, "context": + [ + { "key": "selector", "operator": "equal", "operand": "text.html.markdown - meta.frontmatter - meta.disable-markdown - markup.raw", "match_all": true } + ] + }, + { "keys": ["ctrl+alt+keypad3"], "command": "mde_change_headings_level", "args": {"to": 3}, "context": + [ + { "key": "selector", "operator": "equal", "operand": "text.html.markdown - meta.frontmatter - meta.disable-markdown - markup.raw", "match_all": true } + ] + }, + { "keys": ["ctrl+alt+3"], "command": "mde_change_headings_level", "args": {"to": 3}, "context": + [ + { "key": "selector", "operator": "equal", "operand": "text.html.markdown - meta.frontmatter - meta.disable-markdown - markup.raw", "match_all": true } + ] + }, + { "keys": ["ctrl+alt+keypad4"], "command": "mde_change_headings_level", "args": {"to": 4}, "context": + [ + { "key": "selector", "operator": "equal", "operand": "text.html.markdown - meta.frontmatter - meta.disable-markdown - markup.raw", "match_all": true } + ] + }, + { "keys": ["ctrl+alt+4"], "command": "mde_change_headings_level", "args": {"to": 4}, "context": + [ + { "key": "selector", "operator": "equal", "operand": "text.html.markdown - meta.frontmatter - meta.disable-markdown - markup.raw", "match_all": true } + ] + }, + { "keys": ["ctrl+alt+keypad5"], "command": "mde_change_headings_level", "args": {"to": 5}, "context": + [ + { "key": "selector", "operator": "equal", "operand": "text.html.markdown - meta.frontmatter - meta.disable-markdown - markup.raw", "match_all": true } + ] + }, + { "keys": ["ctrl+alt+5"], "command": "mde_change_headings_level", "args": {"to": 5}, "context": + [ + { "key": "selector", "operator": "equal", "operand": "text.html.markdown - meta.frontmatter - meta.disable-markdown - markup.raw", "match_all": true } + ] + }, + { "keys": ["ctrl+alt+keypad6"], "command": "mde_change_headings_level", "args": {"to": 6}, "context": + [ + { "key": "selector", "operator": "equal", "operand": "text.html.markdown - meta.frontmatter - meta.disable-markdown - markup.raw", "match_all": true } + ] + }, + { "keys": ["ctrl+alt+6"], "command": "mde_change_headings_level", "args": {"to": 6}, "context": + [ + { "key": "selector", "operator": "equal", "operand": "text.html.markdown - meta.frontmatter - meta.disable-markdown - markup.raw", "match_all": true } + ] + }, + { "keys": ["ctrl+alt+."], "command": "mde_change_headings_level", "args": {"by": 1}, "context": + [ + { "key": "selector", "operator": "equal", "operand": "text.html.markdown - meta.frontmatter - meta.disable-markdown - markup.raw", "match_all": true } + ] + }, + { "keys": ["ctrl+alt+,"], "command": "mde_change_headings_level", "args": {"by": -1}, "context": + [ + { "key": "selector", "operator": "equal", "operand": "text.html.markdown - meta.frontmatter - meta.disable-markdown - markup.raw", "match_all": true } + ] + }, + // If nothing is selected, pressing hash in front of heading label increases level by one + { "keys": ["#"], "command": "mde_change_headings_level", "args": {"by": 1}, "context": + [ + { "key": "selector", "operator": "equal", "operand": "text.html.markdown - meta.frontmatter - meta.disable-markdown - markup.raw - markup.kbd", "match_all": true }, + { "key": "setting.mde.auto_match_heading_hashes", "operator": "equal", "operand": true }, + { "key": "selection_empty", "operator": "equal", "operand": true, "match_all": true }, + { "key": "preceding_text", "operator": "regex_match", "operand": "^[\\s>]*#*\\s*$", "match_all": true } + ] + }, + // If nothing is selected, pressing backspace within or directly after leading hashes decreases heading level + { "keys": ["backspace"], "command": "mde_change_headings_level", "args": {"by": -1}, "context": + [ + { "key": "selector", "operator": "equal", "operand": "text.html.markdown - meta.frontmatter - meta.disable-markdown - markup.raw - markup.kbd", "match_all": true }, + { "key": "setting.mde.auto_match_heading_hashes", "operator": "equal", "operand": true }, + { "key": "selection_empty", "operator": "equal", "operand": true, "match_all": true }, + { "key": "preceding_text", "operator": "regex_match", "operand": "^[\\s>]*#+\\s?$", "match_all": true } + ] + }, + // If nothing is selected, pressing delete within or directly in front of leading hashes decreases heading level + { "keys": ["delete"], "command": "mde_change_headings_level", "args": {"by": -1}, "context": + [ + { "key": "selector", "operator": "equal", "operand": "text.html.markdown - meta.frontmatter - meta.disable-markdown - markup.raw - markup.kbd", "match_all": true }, + { "key": "setting.mde.auto_match_heading_hashes", "operator": "equal", "operand": true }, + { "key": "selection_empty", "operator": "equal", "operand": true, "match_all": true }, + { "key": "preceding_text", "operator": "regex_match", "operand": "^[\\s>]*#*\\s*$", "match_all": true }, + { "key": "following_text", "operator": "regex_contains", "operand": "^#", "match_all": true } + ] + }, + { "keys": ["enter"], "command": "run_macro_file", "args": {"file": "Packages/MarkdownEditing/macros/Balance Trailing Hashes.sublime-macro"}, "context": + [ + { "key": "selector", "operator": "equal", "operand": "text.html.markdown - meta.frontmatter - meta.disable-markdown - markup.raw - markup.kbd", "match_all": true }, + { "key": "setting.mde.auto_match_heading_hashes", "operator": "equal", "operand": true }, + { "key": "setting.mde.match_heading_hashes", "operator": "equal", "operand": true }, + { "key": "preceding_text", "operator": "regex_contains", "operand": "^[\\s>]*#+\\s+", "match_all": true }, + { "key": "following_text", "operator": "regex_contains", "operand": "^\\s*$", "match_all": true }, + { "key": "auto_complete_visible", "operator": "equal", "operand": false } + ] + }, + { "keys": ["enter"], "command": "run_macro_file", "args": {"file": "Packages/MarkdownEditing/macros/Balance Trailing Hashes.sublime-macro"}, "context": + [ + { "key": "selector", "operator": "equal", "operand": "text.html.markdown - meta.frontmatter - meta.disable-markdown - markup.raw - markup.kbd", "match_all": true }, + { "key": "setting.mde.auto_match_heading_hashes", "operator": "equal", "operand": true }, + { "key": "setting.mde.match_heading_hashes", "operator": "equal", "operand": true }, + { "key": "preceding_text", "operator": "regex_contains", "operand": "^[\\s>]*#+\\s+", "match_all": true }, + { "key": "following_text", "operator": "regex_contains", "operand": "^\\s*$", "match_all": true }, + { "key": "setting.auto_complete_commit_on_tab" } + ] + }, + { "keys": ["enter"], "command": "run_macro_file", "args": {"file": "Packages/MarkdownEditing/macros/Remove Trailing Hashes.sublime-macro"}, "context": + [ + { "key": "selector", "operator": "equal", "operand": "text.html.markdown - meta.frontmatter - meta.disable-markdown - markup.raw - markup.kbd", "match_all": true }, + { "key": "setting.mde.auto_match_heading_hashes", "operator": "equal", "operand": true }, + { "key": "setting.mde.match_heading_hashes", "operator": "equal", "operand": false }, + { "key": "preceding_text", "operator": "regex_contains", "operand": "^[\\s>]*#+\\s+", "match_all": true }, + { "key": "following_text", "operator": "regex_contains", "operand": "^\\s*$", "match_all": true }, + { "key": "auto_complete_visible", "operator": "equal", "operand": false } + ] + }, + { "keys": ["enter"], "command": "run_macro_file", "args": {"file": "Packages/MarkdownEditing/macros/Remove Trailing Hashes.sublime-macro"}, "context": + [ + { "key": "selector", "operator": "equal", "operand": "text.html.markdown - meta.frontmatter - meta.disable-markdown - markup.raw - markup.kbd", "match_all": true }, + { "key": "setting.mde.auto_match_heading_hashes", "operator": "equal", "operand": true }, + { "key": "setting.mde.match_heading_hashes", "operator": "equal", "operand": false }, + { "key": "preceding_text", "operator": "regex_contains", "operand": "^[\\s>]*#+\\s+", "match_all": true }, + { "key": "following_text", "operator": "regex_contains", "operand": "^\\s*$", "match_all": true }, + { "key": "setting.auto_complete_commit_on_tab" } + ] + }, + { "keys": ["tab"], "command": "mde_complete_underlined_headings", "context": + [ + { "key": "selector", "operator": "equal", "operand": "text.html.markdown - meta.frontmatter - meta.disable-markdown - markup.raw - markup.kbd", "match_all": true }, + { "key": "selection_empty", "operator": "equal", "operand": true, "match_all": true }, + { "key": "preceding_text", "operator": "regex_contains", "operand": "^\\-+$|^\\=+$", "match_all": true }, + { "key": "auto_complete_visible", "operator": "equal", "operand": false, "match_all": true } + ] + }, + { "keys": ["ctrl+shift+alt+pageup"], "command": "mde_goto_previous_heading", "args": {"same_level": true}, "context": + [ + { "key": "selector", "operator": "equal", "operand": "text.html.markdown", "match_all": true }, + { "key": "setting.mde.keymap_disable.goto_previous_heading", "operator": "not_equal", "operand": true } + ] + }, + { "keys": ["ctrl+shift+alt+pagedown"], "command": "mde_goto_next_heading", "args": {"same_level": true}, "context": + [ + { "key": "selector", "operator": "equal", "operand": "text.html.markdown", "match_all": true }, + { "key": "setting.mde.keymap_disable.goto_next_heading", "operator": "not_equal", "operand": true } + ] + }, + { "keys": ["ctrl+shift+pageup"], "command": "mde_goto_previous_heading", "args": {"same_level": false}, "context": + [ + { "key": "selector", "operator": "equal", "operand": "text.html.markdown", "match_all": true }, + { "key": "setting.mde.keymap_disable.goto_previous_heading", "operator": "not_equal", "operand": true } + ] + }, + { "keys": ["ctrl+shift+pagedown"], "command": "mde_goto_next_heading", "args": {"same_level": false}, "context": + [ + { "key": "selector", "operator": "equal", "operand": "text.html.markdown", "match_all": true }, + { "key": "setting.mde.keymap_disable.goto_next_heading", "operator": "not_equal", "operand": true } + ] + }, + + // + // Folding + // + + { "keys": ["ctrl+k", "ctrl+keypad0"], "command": "mde_unfold_all_sections", "context": + [ + { "key": "selector", "operator": "equal", "operand": "text.html.markdown - meta.frontmatter - meta.disable-markdown - markup.raw", "match_all": true } + ] + }, + { "keys": ["ctrl+k", "ctrl+0"], "command": "mde_unfold_all_sections", "context": + [ + { "key": "selector", "operator": "equal", "operand": "text.html.markdown - meta.frontmatter - meta.disable-markdown - markup.raw", "match_all": true } + ] + }, + { "keys": ["ctrl+k", "ctrl+keypad1"], "command": "mde_fold_all_sections", "args": {"target_level": 1}, "context": + [ + { "key": "selector", "operator": "equal", "operand": "text.html.markdown - meta.frontmatter - meta.disable-markdown - markup.raw", "match_all": true } + ] + }, + { "keys": ["ctrl+k", "ctrl+1"], "command": "mde_fold_all_sections", "args": {"target_level": 1}, "context": + [ + { "key": "selector", "operator": "equal", "operand": "text.html.markdown - meta.frontmatter - meta.disable-markdown - markup.raw", "match_all": true } + ] + }, + { "keys": ["ctrl+k", "ctrl+keypad2"], "command": "mde_fold_all_sections", "args": {"target_level": 2}, "context": + [ + { "key": "selector", "operator": "equal", "operand": "text.html.markdown - meta.frontmatter - meta.disable-markdown - markup.raw", "match_all": true } + ] + }, + { "keys": ["ctrl+k", "ctrl+2"], "command": "mde_fold_all_sections", "args": {"target_level": 2}, "context": + [ + { "key": "selector", "operator": "equal", "operand": "text.html.markdown - meta.frontmatter - meta.disable-markdown - markup.raw", "match_all": true } + ] + }, + { "keys": ["ctrl+k", "ctrl+keypad3"], "command": "mde_fold_all_sections", "args": {"target_level": 3}, "context": + [ + { "key": "selector", "operator": "equal", "operand": "text.html.markdown - meta.frontmatter - meta.disable-markdown - markup.raw", "match_all": true } + ] + }, + { "keys": ["ctrl+k", "ctrl+3"], "command": "mde_fold_all_sections", "args": {"target_level": 3}, "context": + [ + { "key": "selector", "operator": "equal", "operand": "text.html.markdown - meta.frontmatter - meta.disable-markdown - markup.raw", "match_all": true } + ] + }, + { "keys": ["ctrl+k", "ctrl+keypad4"], "command": "mde_fold_all_sections", "args": {"target_level": 4}, "context": + [ + { "key": "selector", "operator": "equal", "operand": "text.html.markdown - meta.frontmatter - meta.disable-markdown - markup.raw", "match_all": true } + ] + }, + { "keys": ["ctrl+k", "ctrl+4"], "command": "mde_fold_all_sections", "args": {"target_level": 4}, "context": + [ + { "key": "selector", "operator": "equal", "operand": "text.html.markdown - meta.frontmatter - meta.disable-markdown - markup.raw", "match_all": true } + ] + }, + { "keys": ["ctrl+k", "ctrl+keypad5"], "command": "mde_fold_all_sections", "args": {"target_level": 5}, "context": + [ + { "key": "selector", "operator": "equal", "operand": "text.html.markdown - meta.frontmatter - meta.disable-markdown - markup.raw", "match_all": true } + ] + }, + { "keys": ["ctrl+k", "ctrl+5"], "command": "mde_fold_all_sections", "args": {"target_level": 5}, "context": + [ + { "key": "selector", "operator": "equal", "operand": "text.html.markdown - meta.frontmatter - meta.disable-markdown - markup.raw", "match_all": true } + ] + }, + { "keys": ["ctrl+k", "ctrl+keypad6"], "command": "mde_fold_all_sections", "args": {"target_level": 6}, "context": + [ + { "key": "selector", "operator": "equal", "operand": "text.html.markdown - meta.frontmatter - meta.disable-markdown - markup.raw", "match_all": true } + ] + }, + { "keys": ["ctrl+k", "ctrl+6"], "command": "mde_fold_all_sections", "args": {"target_level": 6}, "context": + [ + { "key": "selector", "operator": "equal", "operand": "text.html.markdown - meta.frontmatter - meta.disable-markdown - markup.raw", "match_all": true } + ] + }, + { "keys": ["ctrl+k", "ctrl+keypad9"], "command": "mde_fold_all_sections", "args": {"target_level": 0}, "context": + [ + { "key": "selector", "operator": "equal", "operand": "text.html.markdown - meta.frontmatter - meta.disable-markdown - markup.raw", "match_all": true } + ] + }, + { "keys": ["ctrl+k", "ctrl+9"], "command": "mde_fold_all_sections", "args": {"target_level": 0}, "context": + [ + { "key": "selector", "operator": "equal", "operand": "text.html.markdown - meta.frontmatter - meta.disable-markdown - markup.raw", "match_all": true } + ] + }, + { "keys": ["shift+tab"], "command": "mde_fold_section", "context": + [ + { "key": "selector", "operator": "equal", "operand": "text.html.markdown - meta.frontmatter - meta.disable-markdown - markup.raw - markup.list", "match_all": true }, + { "key": "setting.mde.keymap_disable.fold_section", "operator": "not_equal", "operand": true }, + { "key": "selection_empty", "operator": "equal", "operand": true, "match_all": true }, + { "key": "has_prev_field", "operator": "equal", "operand": false }, + { "key": "overlay_visible", "operator": "equal", "operand": false }, + { "key": "preceding_text", "operator": "not_regex_match", "operand": "^\\s+", "match_all": true } + ] + }, + { "keys": ["shift+tab"], "command": "mde_fold_section", "context": + [ + { "key": "selector", "operator": "equal", "operand": "text.html.markdown", "match_all": true }, + { "key": "setting.mde.keymap_disable.fold_section", "operator": "not_equal", "operand": true }, + { "key": "selection_empty", "operator": "equal", "operand": false, "match_all": true }, + { "key": "has_prev_field", "operator": "equal", "operand": false }, + { "key": "overlay_visible", "operator": "equal", "operand": false }, + { "key": "text", "operator": "regex_contains", "operand": "^(#{1,6}(?!#))|^(-{3,}|={3,})$"} + ] + }, + { "keys": ["ctrl+shift+tab"], "command": "mde_show_fold_all_sections", "context": + [ + { "key": "selector", "operator": "equal", "operand": "text.html.markdown", "match_all": true }, + { "key": "setting.mde.keymap_disable.show_fold_all_sections", "operator": "not_equal", "operand": true } + ] + }, + + // + // Lists + // + + // Create new GFM Task + { "keys": ["alt+t"], "command": "insert_snippet", "args": {"contents": "* [ ] $0"}, "context": + [ + { "key": "selector", "operator": "equal", "operand": "text.html.markdown - meta.frontmatter - meta.disable-markdown - markup.raw - markup.kbd - meta.table", "match_all": true }, + { "key": "setting.auto_match_enabled", "operator": "equal", "operand": true }, + { "key": "setting.mde.list_align_text", "operator": "equal", "operand": false }, + { "key": "selection_empty", "operator": "equal", "operand": true, "match_all": true }, + { "key": "preceding_text", "operator": "regex_match", "operand": "^[\\s>]*$", "match_all": true }, + { "key": "following_text", "operator": "regex_match", "operand": "^\\s*$", "match_all": true } + ] + }, + { "keys": ["alt+t"], "command": "insert_snippet", "args": {"contents": "* [ ]\t$0"}, "context": + [ + { "key": "selector", "operator": "equal", "operand": "text.html.markdown - meta.frontmatter - meta.disable-markdown - markup.raw - markup.kbd - meta.table", "match_all": true }, + { "key": "setting.auto_match_enabled", "operator": "equal", "operand": true }, + { "key": "setting.mde.list_align_text", "operator": "equal", "operand": true }, + { "key": "selection_empty", "operator": "equal", "operand": true, "match_all": true }, + { "key": "preceding_text", "operator": "regex_match", "operand": "^[\\s>]*$", "match_all": true }, + { "key": "following_text", "operator": "regex_match", "operand": "^\\s*$", "match_all": true } + ] + }, + // Convert List Item to GFM Task + { "keys": ["alt+t"], "command": "run_macro_file", "args": {"file": "Packages/MarkdownEditing/macros/Convert List to Task.sublime-macro"}, "context": + [ + { "key": "selector", "operator": "equal", "operand": "text.html.markdown - meta.frontmatter - meta.disable-markdown - markup.raw - markup.kbd - meta.table", "match_all": true }, + { "key": "setting.auto_match_enabled", "operator": "equal", "operand": true }, + { "key": "setting.mde.list_align_text", "operator": "equal", "operand": false }, + { "key": "selection_empty", "operator": "equal", "operand": true, "match_all": true }, + { "key": "preceding_text", "operator": "regex_match", "operand": "^[\\s>]*[-+*]\\s+$", "match_all": true }, + { "key": "following_text", "operator": "regex_match", "operand": "^\\s*$", "match_all": true } + ] + }, + { "keys": ["alt+t"], "command": "run_macro_file", "args": {"file": "Packages/MarkdownEditing/macros/Convert List to Task Tab.sublime-macro"}, "context": + [ + { "key": "selector", "operator": "equal", "operand": "text.html.markdown - meta.frontmatter - meta.disable-markdown - markup.raw - markup.kbd - meta.table", "match_all": true }, + { "key": "setting.auto_match_enabled", "operator": "equal", "operand": true }, + { "key": "setting.mde.list_align_text", "operator": "equal", "operand": true }, + { "key": "selection_empty", "operator": "equal", "operand": true, "match_all": true }, + { "key": "preceding_text", "operator": "regex_match", "operand": "^[\\s>]*[-+*]\\s+$", "match_all": true }, + { "key": "following_text", "operator": "regex_match", "operand": "^\\s*$", "match_all": true } + ] + }, + // Add line to current list item + { "keys": ["shift+enter"], "command": "insert_snippet", "args": {"contents": "${TM_CURRENT_LINE/^(?:\\s*((?:>\\s*)*)([-+*])(\\s+)).*/\n$1 $3/}"}, "context": + [ + { "key": "selector", "operator": "equal", "operand": "text.html.markdown - markup.raw", "match_all": true }, + { "key": "preceding_text", "operator": "regex_contains", "operand": "^[\\s>]*[-+*](?:\\s+\\S|\\s*$)", "match_all": true } + ] + }, + // Extend lists (also in block quotes) + { "keys": ["enter"], "command": "insert_snippet", "args": {"contents": "${TM_CURRENT_LINE/^(?:\\s*((?:>\\s*)*)([-+*])(\\s+)).*/\n$1$2$3/}"}, "context": + [ + { "key": "selector", "operator": "equal", "operand": "text.html.markdown - meta.frontmatter - meta.disable-markdown - markup.raw", "match_all": true }, + { "key": "preceding_text", "operator": "regex_contains", "operand": "^[\\s>]*[-+*](?:\\s+\\S|\\s*$)", "match_all": true }, + { "key": "auto_complete_visible", "operator": "equal", "operand": false } + ] + }, + { "keys": ["enter"], "command": "insert_snippet", "args": {"contents": "${TM_CURRENT_LINE/^(?:\\s*((?:>\\s*)*)([-+*])(\\s+)).*/\n$1$2$3/}"}, "context": + [ + { "key": "selector", "operator": "equal", "operand": "text.html.markdown - meta.frontmatter - meta.disable-markdown - markup.raw", "match_all": true }, + { "key": "preceding_text", "operator": "regex_contains", "operand": "^[\\s>]*[-+*](?:\\s+\\S|\\s*$)", "match_all": true }, + { "key": "setting.auto_complete_commit_on_tab" } + ] + }, + // Extend lists with GFM tasks (also in block quotes) + { "keys": ["enter"], "command": "insert_snippet", "args": {"contents": "${TM_CURRENT_LINE/^(?:\\s*((?:>\\s*)*)([-+*])(\\s+)\\[[ xX]\\](\\s+)).*/\n$1$2$3[ ]$4/}"}, "context": + [ + { "key": "selector", "operator": "equal", "operand": "text.html.markdown - meta.frontmatter - meta.disable-markdown - markup.raw", "match_all": true }, + { "key": "preceding_text", "operator": "regex_contains", "operand": "^([\\s>]*([-+*])\\s+)\\[[ xX]\\](?:\\s+\\S|\\s*$)", "match_all": true }, + { "key": "auto_complete_visible", "operator": "equal", "operand": false } + ] + }, + { "keys": ["enter"], "command": "insert_snippet", "args": {"contents": "${TM_CURRENT_LINE/^(?:\\s*((?:>\\s*)*)([-+*])(\\s+)\\[[ xX]\\](\\s+)).*/\n$1$2$3[ ]$4/}"}, "context": + [ + { "key": "selector", "operator": "equal", "operand": "text.html.markdown - meta.frontmatter - meta.disable-markdown - markup.raw", "match_all": true }, + { "key": "preceding_text", "operator": "regex_contains", "operand": "^([\\s>]*([-+*])\\s+)\\[[ xX]\\](?:\\s+\\S|\\s*$)", "match_all": true }, + { "key": "setting.auto_complete_commit_on_tab" } + ] + }, + // Extend Numbered Lists (also in block quotes) + { "keys": ["enter"], "command": "mde_number_list", "context": + [ + { "key": "selector", "operator": "equal", "operand": "text.html.markdown - meta.frontmatter - meta.disable-markdown - markup.raw", "match_all": true }, + { "key": "preceding_text", "operator": "regex_contains", "operand": "^[\\s>]*\\d+[.)]", "match_all": true }, + { "key": "auto_complete_visible", "operator": "equal", "operand": false } + ] + }, + { "keys": ["enter"], "command": "mde_number_list", "context": + [ + { "key": "selector", "operator": "equal", "operand": "text.html.markdown - meta.frontmatter - meta.disable-markdown - markup.raw", "match_all": true }, + { "key": "preceding_text", "operator": "regex_contains", "operand": "^[\\s>]*\\d+[.)]", "match_all": true }, + { "key": "setting.auto_complete_commit_on_tab" } + ] + }, + // Remove empty list item including GFM tasks + { "keys": ["enter"], "command": "run_macro_file", "args": {"file": "Packages/MarkdownEditing/macros/Remove Empty List Item.sublime-macro"}, "context": + [ + { "key": "selector", "operator": "equal", "operand": "text.html.markdown - meta.frontmatter - meta.disable-markdown - markup.raw", "match_all": true }, + { "key": "preceding_text", "operator": "regex_match", "operand": "^[\\s>]*([-+*]|\\d+[.)])(?:\\s+\\[[ xX]\\])?\\s*$", "match_all": true }, + { "key": "following_text", "operator": "regex_match", "operand": "^\\s*$", "match_all": true }, + { "key": "auto_complete_visible", "operator": "equal", "operand": false } + ] + }, + { "keys": ["enter"], "command": "run_macro_file", "args": {"file": "Packages/MarkdownEditing/macros/Remove Empty List Item.sublime-macro"}, "context": + [ + { "key": "selector", "operator": "equal", "operand": "text.html.markdown - meta.frontmatter - meta.disable-markdown - markup.raw", "match_all": true }, + { "key": "preceding_text", "operator": "regex_match", "operand": "^[\\s>]*([-+*]|\\d+[.)])(?:\\s+\\[[ xX]\\])?\\s*$", "match_all": true }, + { "key": "following_text", "operator": "regex_match", "operand": "^\\s*$", "match_all": true }, + { "key": "setting.auto_complete_commit_on_tab" } + ] + }, + { "keys": ["backspace"], "command": "run_macro_file", "args": {"file": "Packages/MarkdownEditing/macros/Remove Empty List Item.sublime-macro"}, "context": + [ + { "key": "selector", "operator": "equal", "operand": "text.html.markdown - meta.frontmatter - meta.disable-markdown - markup.raw", "match_all": true }, + { "key": "preceding_text", "operator": "regex_match", "operand": "^[\\s>]*([-+*]|\\d+[.)])(?:\\s+\\[[ xX]\\])?\\s?$", "match_all": true }, + { "key": "following_text", "operator": "regex_match", "operand": "^\\s*$", "match_all": true } + ] + }, + // Join content of next into current line after removing its leading blockquote, list and GFM task punctuation + { "keys": ["delete"], "command": "mde_join_lines", "context": + [ + { "key": "selector", "operator": "equal", "operand": "text.html.markdown markup.quote, text.html.markdown markup.list" }, + { "key": "selection_empty", "operator": "equal", "operand": true, "match_all": true }, + { "key": "following_text", "operator": "regex_match", "operand": "^$", "match_all": true } + ] + }, + { "keys": ["ctrl+shift+j"], "command": "mde_join_lines", "context": + [ + { "key": "selector", "operator": "equal", "operand": "text.html.markdown markup.quote, text.html.markdown markup.list" } + ] + }, + // Indent list item if caret is in front of bullets + { "keys": ["tab"], "command": "mde_indent_list_item", "context": + [ + { "key": "selector", "operator": "equal", "operand": "text.html.markdown - meta.frontmatter - meta.disable-markdown - markup.raw", "match_all": true }, + { "key": "selection_empty", "operator": "equal", "operand": true, "match_all": true }, + { "key": "has_next_field", "operator": "equal", "operand": false }, + { "key": "overlay_visible", "operator": "equal", "operand": false }, + { "key": "preceding_text", "operator": "regex_match", "operand": "^[\\s>]*$", "match_all": true }, + { "key": "following_text", "operator": "regex_contains", "operand": "^\\s*[-+*]\\s", "match_all": true } + ] + }, + // Indent list item, if caret is directly behind bullet only if followed by whitespace + // Hitting "tab" directly after new list bullet should insert \t otherwise + { "keys": ["tab"], "command": "mde_indent_list_item", "context": + [ + { "key": "selector", "operator": "equal", "operand": "text.html.markdown - meta.frontmatter - meta.disable-markdown - markup.raw", "match_all": true }, + { "key": "selection_empty", "operator": "equal", "operand": true, "match_all": true }, + { "key": "has_next_field", "operator": "equal", "operand": false }, + { "key": "overlay_visible", "operator": "equal", "operand": false }, + { "key": "preceding_text", "operator": "regex_match", "operand": "^[\\s>]*[-+*]$", "match_all": true }, + { "key": "following_text", "operator": "regex_contains", "operand": "^\\s", "match_all": true } + ] + }, + // Indent list item if caret is behind bullets + { "keys": ["tab"], "command": "mde_indent_list_item", "context": + [ + { "key": "selector", "operator": "equal", "operand": "text.html.markdown - meta.frontmatter - meta.disable-markdown - markup.raw", "match_all": true }, + { "key": "selection_empty", "operator": "equal", "operand": true, "match_all": true }, + { "key": "has_next_field", "operator": "equal", "operand": false }, + { "key": "overlay_visible", "operator": "equal", "operand": false }, + { "key": "preceding_text", "operator": "regex_match", "operand": "^[\\s>]*[-+*]\\s*$", "match_all": true }, + { "key": "following_text", "operator": "not_regex_match", "operand": "(?:-{2,}|={2,}|[+*])", "match_all": true } + ] + }, + // Indent selected list items + { "keys": ["tab"], "command": "mde_indent_list_item", "context": + [ + { "key": "selector", "operator": "equal", "operand": "text.html.markdown - meta.frontmatter - meta.disable-markdown - markup.raw", "match_all": true }, + { "key": "selection_empty", "operator": "equal", "operand": false, "match_all": true }, + { "key": "has_next_field", "operator": "equal", "operand": false }, + { "key": "overlay_visible", "operator": "equal", "operand": false } + ] + }, + // Unindent list item no matter of caret position if `shift_tab_unindent` is set + { "keys": ["shift+tab"], "command": "mde_unindent_list_item", "context": + [ + { "key": "selector", "operator": "equal", "operand": "text.html.markdown", "match_all": true }, + { "key": "setting.shift_tab_unindent", "operator": "equal", "operand": true }, + { "key": "has_prev_field", "operator": "equal", "operand": false }, + { "key": "overlay_visible", "operator": "equal", "operand": false }, + { "key": "preceding_text", "operator": "regex_contains", "operand": "^[\\s>]*[-+*]\\s", "match_all": true } + ] + }, + // Unindent list item if caret is in front of bullets + { "keys": ["shift+tab"], "command": "mde_unindent_list_item", "context": + [ + { "key": "selector", "operator": "equal", "operand": "text.html.markdown", "match_all": true }, + { "key": "has_prev_field", "operator": "equal", "operand": false }, + { "key": "overlay_visible", "operator": "equal", "operand": false }, + { "key": "preceding_text", "operator": "regex_match", "operand": "^[\\s>]*$", "match_all": true }, + { "key": "following_text", "operator": "regex_contains", "operand": "^\\s*[-+*]\\s", "match_all": true } + ] + }, + // Unindent list item if caret is behind bullets + { "keys": ["shift+tab"], "command": "mde_unindent_list_item", "context": + [ + { "key": "selector", "operator": "equal", "operand": "text.html.markdown", "match_all": true }, + { "key": "has_prev_field", "operator": "equal", "operand": false }, + { "key": "overlay_visible", "operator": "equal", "operand": false }, + { "key": "preceding_text", "operator": "regex_match", "operand": "^[\\s>]*[-+*]\\s*$", "match_all": true }, + { "key": "following_text", "operator": "not_regex_match", "operand": "(?:-{2,}|={2,})", "match_all": true } + ] + }, + // Unindent list item if caret is at eol + { "keys": ["shift+tab"], "command": "mde_unindent_list_item", "context": + [ + { "key": "selector", "operator": "equal", "operand": "text.html.markdown", "match_all": true }, + { "key": "has_prev_field", "operator": "equal", "operand": false }, + { "key": "overlay_visible", "operator": "equal", "operand": false }, + { "key": "preceding_text", "operator": "regex_contains", "operand": "^[\\s>]*[-+*]\\s", "match_all": true }, + { "key": "following_text", "operator": "regex_match", "operand": "^$" } + ] + }, + // Unindent selected list items + { "keys": ["shift+tab"], "command": "mde_unindent_list_item", "context": + [ + { "key": "selector", "operator": "equal", "operand": "text.html.markdown markup.list", "match_all": true }, + { "key": "selection_empty", "operator": "equal", "operand": false, "match_all": true }, + { "key": "has_prev_field", "operator": "equal", "operand": false }, + { "key": "overlay_visible", "operator": "equal", "operand": false } + ] + }, + // Toggle GFM tasks + { "keys": ["alt+x"], "command": "mde_toggle_task_list_item", "context": + [ + { "key": "selector", "operator": "equal", "operand": "text.html.markdown & (markup.list | markup.quote)", "match_all": true } + ] + }, + + // + // Quotes + // + + // Convert to blockquote + { "keys": [">"], "command": "run_macro_file", "args": {"file": "Packages/MarkdownEditing/macros/Convert to Blockquote.sublime-macro"}, "context": + [ + { "key": "selector", "operator": "equal", "operand": "text.html.markdown - meta.frontmatter - meta.disable-markdown - markup.raw - markup.kbd", "match_all": true }, + { "key": "selection_empty", "operator": "equal", "operand": false, "match_all": true } + ] + }, + // Extend blockquote (ignore headings, lists and tasks) + { "keys": ["enter"], "command": "insert_snippet", "args": {"contents": "${TM_CURRENT_LINE/^\\s*((?:>\\s*)*(?:>\\s?)).*/\n$1/}"}, "context": + [ + { "key": "selector", "operator": "equal", "operand": "text.html.markdown markup.quote", "match_all": true }, + { "key": "preceding_text", "operator": "regex_contains", "operand": "^\\s*(?:>\\s*)+(?![-+*>#\\s]|\\d+[.)])", "match_all": true }, + { "key": "auto_complete_visible", "operator": "equal", "operand": false } + ] + }, + { "keys": ["enter"], "command": "insert_snippet", "args": {"contents": "${TM_CURRENT_LINE/^\\s*((?:>\\s*)*(?:>\\s?)).*/\n$1/}"}, "context": + [ + { "key": "selector", "operator": "equal", "operand": "text.html.markdown markup.quote", "match_all": true }, + { "key": "preceding_text", "operator": "regex_contains", "operand": "^\\s*(?:>\\s*)+(?![-+*>#\\s]|\\d+[.)])", "match_all": true }, + { "key": "setting.auto_complete_commit_on_tab" } + ] + }, + // Remove empty blockquote line + // { "keys": ["enter"], "command": "run_macro_file", "args": {"file": "Packages/MarkdownEditing/macros/Remove Empty Blockquote Line.sublime-macro"}, "context": + // [ + // { "key": "selector", "operator": "equal", "operand": "text.html.markdown markup.quote", "match_all": true }, + // { "key": "preceding_text", "operator": "regex_match", "operand": "^\\s*(>\\s*)+$", "match_all": true }, + // { "key": "following_text", "operator": "regex_match", "operand": "^\\s*$", "match_all": true }, + // { "key": "auto_complete_visible", "operator": "equal", "operand": false } + // ] + // }, + // { "keys": ["enter"], "command": "run_macro_file", "args": {"file": "Packages/MarkdownEditing/macros/Remove Empty Blockquote Line.sublime-macro"}, "context": + // [ + // { "key": "selector", "operator": "equal", "operand": "text.html.markdown markup.quote", "match_all": true }, + // { "key": "preceding_text", "operator": "regex_match", "operand": "^\\s*(>\\s*)+$", "match_all": true }, + // { "key": "following_text", "operator": "regex_match", "operand": "^\\s*$", "match_all": true }, + // { "key": "setting.auto_complete_commit_on_tab" } + // ] + // }, + { "keys": ["backspace"], "command": "run_macro_file", "args": {"file": "Packages/MarkdownEditing/macros/Remove Empty Blockquote Line.sublime-macro"}, "context": + [ + { "key": "selector", "operator": "equal", "operand": "text.html.markdown markup.quote", "match_all": true }, + { "key": "preceding_text", "operator": "regex_match", "operand": "^\\s*(>\\s*)*(>\\s?)$", "match_all": true }, + { "key": "following_text", "operator": "regex_match", "operand": "^\\s*$", "match_all": true } + ] + }, + // Indent blockquote + { "keys": ["ctrl+shift+."], "command": "mde_indent_quote", "context": + [ + { "key": "selector", "operator": "equal", "operand": "text.html.markdown", "match_all": true } + ] + }, + // Unindent blockquote + { "keys": ["ctrl+shift+,"], "command": "mde_unindent_quote", "context": + [ + { "key": "selector", "operator": "equal", "operand": "text.html.markdown", "match_all": true }, + { "key": "preceding_text", "operator": "regex_contains", "operand": "(> )+", "match_all": true } + ] + }, + + // + // References + // + + // Surround with <> on URLs, regex copied from https://mathiasbynens.be/demo/url-regex, @diegoperini (502 chars) + { "keys": ["<"], "command": "insert_snippet", "args": {"contents": "<${0:$SELECTION}>"}, "context": + [ + { "key": "selector", "operator": "equal", "operand": "text.html.markdown - meta.frontmatter - meta.disable-markdown - markup.raw - markup.kbd", "match_all": true }, + { "key": "setting.auto_match_enabled", "operator": "equal", "operand": true }, + { "key": "selection_empty", "operator": "equal", "operand": false, "match_all": true }, + { "key": "text", "operator": "regex_match", "operand": "(?:(?:https?|ftp)://)(?:\\S+(?::\\S*)?@)?(?:(?!10(?:\\.\\d{1,3}){3})(?!127(?:\\.\\d{1,3}){3})(?!169\\.254(?:\\.\\d{1,3}){2})(?!192\\.168(?:\\.\\d{1,3}){2})(?!172\\.(?:1[6-9]|2\\d|3[0-1])(?:\\.\\d{1,3}){2})(?:[1-9]\\d?|1\\d\\d|2[01]\\d|22[0-3])(?:\\.(?:1?\\d{1,2}|2[0-4]\\d|25[0-5])){2}(?:\\.(?:[1-9]\\d?|1\\d\\d|2[0-4]\\d|25[0-4]))|(?:(?:[a-z\\x{00a1}-\\x{ffff}0-9]+-?)*[a-z\\x{00a1}-\\x{ffff}0-9]+)(?:\\.(?:[a-z\\x{00a1}-\\x{ffff}0-9]+-?)*[a-z\\x{00a1}-\\x{ffff}0-9]+)*(?:\\.(?:[a-z\\x{00a1}-\\x{ffff}]{2,})))(?::\\d{2,5})?(?:/[^\\s]*)?", "match_all": true } + ] + }, + // modify [] pairing so that selection is removed after pairing, ready for [] or () + { "keys": ["["], "command": "insert_snippet", "args": {"contents": "[$SELECTION]$0"}, "context": + [ + { "key": "selector", "operator": "equal", "operand": "text.html.markdown - meta.frontmatter - meta.disable-markdown - markup.raw - markup.kbd", "match_all": true }, + { "key": "setting.auto_match_enabled", "operator": "equal", "operand": true }, + { "key": "selection_empty", "operator": "equal", "operand": false, "match_all": true } + ] + }, + // inline image insertion + { "keys": ["ctrl+shift+k"], "command": "mde_reference_new_inline_image", "context": + [ + { "key": "selector", "operator": "equal", "operand": "text.html.markdown", "match_all": true }, + { "key": "setting.mde.keymap_disable.reference_new_inline_image", "operator": "not_equal", "operand": true } + ] + }, + // run paste as link command on selected text + { "keys": ["ctrl+alt+v"], "command": "mde_reference_new_inline_link", "context": + [ + { "key": "selector", "operator": "equal", "operand": "text.html.markdown", "match_all": true }, + { "key": "setting.mde.keymap_disable.reference_new_inline_link", "operator": "not_equal", "operand": true } + ] + }, + // create new footnote + { "keys": ["alt+shift+6"], "command": "mde_reference_new_footnote", "context": + [ + { "key": "selector", "operator": "equal", "operand": "text.html.markdown", "match_all": true }, + { "key": "setting.mde.keymap_disable.reference_new_footnote", "operator": "not_equal", "operand": true } + ] + }, + // create new reference + { "keys": ["ctrl+alt+r"], "command": "mde_reference_new_reference", "context": + [ + { "key": "selector", "operator": "equal", "operand": "text.html.markdown", "match_all": true }, + { "key": "setting.mde.keymap_disable.reference_new_reference", "operator": "not_equal", "operand": true } + ] + }, + // extend numbered reference if auto completion panel is not visible + { "keys": ["enter"], "command": "mde_add_numbered_reference_definition", "context": + [ + { "key": "selector", "operator": "equal", "operand": "text.html.markdown - meta.frontmatter - meta.disable-markdown - markup.raw", "match_all": true }, + { "key": "preceding_text", "operator": "regex_contains", "operand": "^\\s*\\[.*\\d+\\]:", "match_all": true }, + { "key": "auto_complete_visible", "operand": false } + ] + }, + // extend numbered reference if auto-completions are commited via tab only + { "keys": ["enter"], "command": "mde_add_numbered_reference_definition", "context": + [ + { "key": "selector", "operator": "equal", "operand": "text.html.markdown - meta.frontmatter - meta.disable-markdown - markup.raw", "match_all": true }, + { "key": "preceding_text", "operator": "regex_contains", "operand": "^\\s*\\[.*\\d+\\]:", "match_all": true }, + { "key": "setting.auto_complete_commit_on_tab" } + ] + }, + // jump to reference + { "keys": ["ctrl+alt+g"], "command": "mde_reference_jump", "context": + [ + { "key": "selector", "operator": "equal", "operand": "text.html.markdown", "match_all": true }, + { "key": "setting.mde.keymap_disable.reference_jump", "operator": "not_equal", "operand": true } + ] + }, + // organize references + { "keys": ["ctrl+alt+s"], "command": "mde_reference_organize", "context": + [ + { "key": "selector", "operator": "equal", "operand": "text.html.markdown", "match_all": true }, + { "key": "setting.mde.keymap_disable.reference_organize", "operator": "not_equal", "operand": true } + ] + }, + + // + // CriticMarkup + // + + // insert new addition or mark selection for addition + { "keys": ["alt+c", "alt+a"], "command": "insert_snippet", "args": {"name": "Packages/MarkdownEditing/snippets/Critic Addition.sublime-snippet"}, "context": + [ + { "key": "selector", "operator": "equal", "operand": "text.html.markdown - meta.frontmatter - meta.disable-markdown - markup.critic - meta.code-fence - markup.raw - markup.kbd", "match_all": true } + ] + }, + // commit addition + { "keys": ["alt+enter"], "command": "run_macro_file", "args": {"file": "Packages/MarkdownEditing/macros/Commit Critic Addition.sublime-macro"}, "context": + [ + { "key": "selector", "operator": "equal", "operand": "text.html.markdown markup.critic.addition", "match_all": true }, + { "key": "selection_empty", "operator": "equal", "operand": true, "match_all": false } + ] + }, + // discard addition + { "keys": ["alt+backspace"], "command": "run_macro_file", "args": {"file": "Packages/MarkdownEditing/macros/Discard Critic Addition.sublime-macro"}, "context": + [ + { "key": "selector", "operator": "equal", "operand": "text.html.markdown markup.critic.addition", "match_all": true }, + { "key": "selection_empty", "operator": "equal", "operand": true, "match_all": false } + ] + }, + + // insert comment or convert selection into comment + { "keys": ["alt+c", "alt+c"], "command": "insert_snippet", "args": {"name": "Packages/MarkdownEditing/snippets/Critic Comment.sublime-snippet"}, "context": + [ + { "key": "selector", "operator": "equal", "operand": "text.html.markdown - meta.frontmatter - meta.disable-markdown - markup.critic - meta.code-fence - markup.raw - markup.kbd", "match_all": true } + ] + }, + // remove comment + { "keys": ["alt+c", "alt+c"], "command": "run_macro_file", "args": {"file": "Packages/MarkdownEditing/macros/Discard Critic Comment.sublime-macro"}, "context": + [ + { "key": "selector", "operator": "equal", "operand": "text.html.markdown markup.critic.comment", "match_all": true }, + { "key": "selection_empty", "operator": "equal", "operand": true, "match_all": false } + ] + }, + { "keys": ["alt+enter"], "command": "run_macro_file", "args": {"file": "Packages/MarkdownEditing/macros/Discard Critic Comment.sublime-macro"}, "context": + [ + { "key": "selector", "operator": "equal", "operand": "text.html.markdown markup.critic.comment", "match_all": true }, + { "key": "selection_empty", "operator": "equal", "operand": true, "match_all": false } + ] + }, + { "keys": ["alt+backspace"], "command": "run_macro_file", "args": {"file": "Packages/MarkdownEditing/macros/Discard Critic Comment.sublime-macro"}, "context": + [ + { "key": "selector", "operator": "equal", "operand": "text.html.markdown markup.critic.comment", "match_all": true }, + { "key": "selection_empty", "operator": "equal", "operand": true, "match_all": false } + ] + }, + + // mark word for deletion + { "keys": ["alt+c", "alt+d"], "command": "run_macro_file", "args": {"file": "Packages/MarkdownEditing/macros/Transform Word - Critic Deletion.sublime-macro"}, "context": + [ + { "key": "selector", "operator": "equal", "operand": "text.html.markdown - meta.frontmatter - meta.disable-markdown - markup.critic - meta.code-fence - markup.raw - markup.kbd", "match_all": true }, + { "key": "selection_empty", "operator": "equal", "operand": true, "match_all": false } + ] + }, + // mark selection for deletion + { "keys": ["alt+c", "alt+d"], "command": "insert_snippet", "args": {"name": "Packages/MarkdownEditing/snippets/Critic Deletion.sublime-snippet"}, "context": + [ + { "key": "selector", "operator": "equal", "operand": "text.html.markdown - meta.frontmatter - meta.disable-markdown - markup.critic - meta.code-fence - markup.raw - markup.kbd", "match_all": true }, + { "key": "selection_empty", "operator": "equal", "operand": false, "match_all": true } + ] + }, + // commit deletion + { "keys": ["alt+enter"], "command": "run_macro_file", "args": {"file": "Packages/MarkdownEditing/macros/Commit Critic Deletion.sublime-macro"}, "context": + [ + { "key": "selector", "operator": "equal", "operand": "text.html.markdown markup.critic.deletion", "match_all": true }, + { "key": "selection_empty", "operator": "equal", "operand": true, "match_all": false } + ] + }, + // discard deletion + { "keys": ["alt+backspace"], "command": "run_macro_file", "args": {"file": "Packages/MarkdownEditing/macros/Discard Critic Deletion.sublime-macro"}, "context": + [ + { "key": "selector", "operator": "equal", "operand": "text.html.markdown markup.critic.deletion", "match_all": true }, + { "key": "selection_empty", "operator": "equal", "operand": true, "match_all": false } + ] + }, + + // mark word for highlight + { "keys": ["alt+c", "alt+h"], "command": "run_macro_file", "args": {"file": "Packages/MarkdownEditing/macros/Transform Word - Critic Highlight.sublime-macro"}, "context": + [ + { "key": "selector", "operator": "equal", "operand": "text.html.markdown - meta.frontmatter - meta.disable-markdown - markup.critic - meta.code-fence - markup.raw - markup.kbd", "match_all": true }, + { "key": "selection_empty", "operator": "equal", "operand": true, "match_all": false } + ] + }, + // mark selection for highlighting + { "keys": ["alt+c", "alt+h"], "command": "insert_snippet", "args": {"name": "Packages/MarkdownEditing/snippets/Critic Highlight.sublime-snippet"}, "context": + [ + { "key": "selector", "operator": "equal", "operand": "text.html.markdown - meta.frontmatter - meta.disable-markdown - markup.critic - meta.code-fence - markup.raw - markup.kbd", "match_all": true }, + { "key": "selection_empty", "operator": "equal", "operand": false, "match_all": true } + ] + }, + // remove highlight + { "keys": ["alt+enter"], "command": "run_macro_file", "args": {"file": "Packages/MarkdownEditing/macros/Discard Critic Highlight.sublime-macro"}, "context": + [ + { "key": "selector", "operator": "equal", "operand": "text.html.markdown markup.critic.highlight", "match_all": true }, + { "key": "selection_empty", "operator": "equal", "operand": true, "match_all": false } + ] + }, + { "keys": ["alt+backspace"], "command": "run_macro_file", "args": {"file": "Packages/MarkdownEditing/macros/Discard Critic Highlight.sublime-macro"}, "context": + [ + { "key": "selector", "operator": "equal", "operand": "text.html.markdown markup.critic.highlight", "match_all": true }, + { "key": "selection_empty", "operator": "equal", "operand": true, "match_all": false } + ] + }, + + // mark word for substitution + { "keys": ["alt+c", "alt+s"], "command": "run_macro_file", "args": {"file": "Packages/MarkdownEditing/macros/Transform Word - Critic Substitution.sublime-macro"}, "context": + [ + { "key": "selector", "operator": "equal", "operand": "text.html.markdown - meta.frontmatter - meta.disable-markdown - markup.critic - meta.code-fence - markup.raw - markup.kbd", "match_all": true }, + { "key": "selection_empty", "operator": "equal", "operand": true, "match_all": false } + ] + }, + // mark selection for substitution + { "keys": ["alt+c", "alt+s"], "command": "insert_snippet", "args": {"name": "Packages/MarkdownEditing/snippets/Critic Substitution.sublime-snippet"}, "context": + [ + { "key": "selector", "operator": "equal", "operand": "text.html.markdown - meta.frontmatter - meta.disable-markdown - markup.critic - meta.code-fence - markup.raw - markup.kbd", "match_all": true }, + { "key": "selection_empty", "operator": "equal", "operand": false, "match_all": true } + ] + }, + // commit substitution + { "keys": ["alt+enter"], "command": "run_macro_file", "args": {"file": "Packages/MarkdownEditing/macros/Commit Critic Substitution.sublime-macro"}, "context": + [ + { "key": "selector", "operator": "equal", "operand": "text.html.markdown markup.critic.substitution", "match_all": true }, + { "key": "selection_empty", "operator": "equal", "operand": true, "match_all": false } + ] + }, + // discard substitution + { "keys": ["alt+backspace"], "command": "run_macro_file", "args": {"file": "Packages/MarkdownEditing/macros/Discard Critic Substitution.sublime-macro"}, "context": + [ + { "key": "selector", "operator": "equal", "operand": "text.html.markdown markup.critic.substitution", "match_all": true }, + { "key": "selection_empty", "operator": "equal", "operand": true, "match_all": false } + ] + }, + + // + // Wiki + // + + { "keys": ["ctrl+alt+h"], "command": "mde_open_home_page", "context": + [ + { "key": "selector", "operator": "equal", "operand": "text.html.markdown", "match_all": true }, + { "key": "setting.mde.keymap_disable.open_home_page", "operator": "not_equal", "operand": true } + ] + }, + { "keys": ["ctrl+alt+d"], "command": "mde_open_page", "context": + [ + { "key": "selector", "operator": "equal", "operand": "meta.link.wiki.markdown", "match_all": true }, + { "key": "setting.mde.keymap_disable.open_page", "operator": "not_equal", "operand": true } + ] + }, + { "keys": ["ctrl+alt+d"], "command": "mde_make_page_reference", "context": + [ + { "key": "selector", "operator": "equal", "operand": "text.html.markdown - (meta.link.wiki | markup.underline.link)", "match_all": true }, + { "key": "setting.mde.keymap_disable.make_page_reference", "operator": "not_equal", "operand": true } + ] + }, + { "keys": ["ctrl+alt+x"], "command": "mde_list_back_links", "context": + [ + { "key": "selector", "operator": "equal", "operand": "text.html.markdown", "match_all": true }, + { "key": "setting.mde.keymap_disable.list_back_links", "operator": "not_equal", "operand": true } + ] + }, + { "keys": ["ctrl+alt+j"], "command": "mde_open_journal", "context": + [ + { "key": "selector", "operator": "equal", "operand": "text.html.markdown", "match_all": true }, + { "key": "setting.mde.keymap_disable.open_journal", "operator": "not_equal", "operand": true } + ] + } ] diff --git a/Default (OSX).sublime-keymap b/Default (OSX).sublime-keymap index 903772b1..8a81db14 100644 --- a/Default (OSX).sublime-keymap +++ b/Default (OSX).sublime-keymap @@ -1,704 +1,1193 @@ [ - // selection pairing with *, _ and ` - { "keys": ["*"], "command": "insert_snippet", "args": {"contents": "*$0*"}, "context": - [ - { "key": "setting.auto_match_enabled", "operator": "equal", "operand": true }, - { "key": "selection_empty", "operator": "equal", "operand": true, "match_all": true }, - { "key": "following_text", "operator": "regex_contains", "operand": "^(?:\t| |\\)|]|\\}|$)", "match_all": true }, - { "key": "preceding_text", "operator": "not_regex_contains", "operand": "['a-zA-Z0-9_*]$", "match_all": true }, - { "key": "eol_selector", "operator": "not_equal", "operand": "string.quoted.single", "match_all": true }, - { "key": "selector", "operator": "equal", "operand": "text.html.markdown", "match_all": true }, - { "key": "selector", "operator": "not_equal", "operand": "markup.raw", "match_all": true } - ] - }, - { "keys": ["*"], "command": "run_macro_file", "args": {"file": "Packages/MarkdownEditing/macros/Skip Closing Character.sublime-macro"}, "context": - [ - { "key": "selection_empty", "operator": "equal", "operand": true, "match_all": true }, - { "key": "following_text", "operator": "regex_contains", "operand": "^\\*", "match_all": true }, - { "key": "selector", "operator": "equal", "operand": "text.html.markdown", "match_all": true }, - { "key": "selector", "operator": "not_equal", "operand": "markup.raw", "match_all": true } - ] - }, - { "keys": ["*"], "command": "insert_snippet", "args": {"contents": "*${0:$SELECTION}*"}, "context": - [ - { "key": "setting.auto_match_enabled", "operator": "equal", "operand": true }, - { "key": "selection_empty", "operator": "equal", "operand": false, "match_all": true }, - { "key": "selector", "operator": "equal", "operand": "text.html.markdown", "match_all": true }, - { "key": "selector", "operator": "not_equal", "operand": "markup.raw", "match_all": true } - ] - }, - { "keys": ["backspace"], "command": "run_macro_file", "args": {"file": "Packages/Default/Delete Left Right.sublime-macro"}, "context": - [ - { "key": "setting.auto_match_enabled", "operator": "equal", "operand": true }, - { "key": "selection_empty", "operator": "equal", "operand": true, "match_all": true }, - { "key": "preceding_text", "operator": "regex_contains", "operand": "\\*$", "match_all": true }, - { "key": "following_text", "operator": "regex_contains", "operand": "^\\*", "match_all": true }, - { "key": "selector", "operator": "equal", "operand": "text.html.markdown", "match_all": true }, - { "key": "selector", "operator": "not_equal", "operand": "markup.raw", "match_all": true } - ] - }, - { "keys": [" "], "command": "run_macro_file", "args": {"file": "Packages/MarkdownEditing/macros/Start List Item.sublime-macro"}, "context": - [ - { "key": "setting.auto_match_enabled", "operator": "equal", "operand": true }, - { "key": "selection_empty", "operator": "equal", "operand": true, "match_all": true }, - { "key": "preceding_text", "operator": "regex_contains", "operand": "\\*$", "match_all": true }, - { "key": "following_text", "operator": "regex_contains", "operand": "^\\*", "match_all": true }, - { "key": "selector", "operator": "equal", "operand": "text.html.markdown", "match_all": true }, - { "key": "selector", "operator": "not_equal", "operand": "markup.raw", "match_all": true } - ] - }, - { "keys": ["tab"], "command": "run_macro_file", "args": {"file": "Packages/MarkdownEditing/macros/Start List Item Tab.sublime-macro"}, "context": - [ - { "key": "setting.auto_match_enabled", "operator": "equal", "operand": true }, - { "key": "selection_empty", "operator": "equal", "operand": true, "match_all": true }, - { "key": "preceding_text", "operator": "regex_contains", "operand": "\\*$", "match_all": true }, - { "key": "following_text", "operator": "regex_contains", "operand": "^\\*", "match_all": true }, - { "key": "selector", "operator": "equal", "operand": "text.html.markdown", "match_all": true }, - { "key": "selector", "operator": "not_equal", "operand": "markup.raw", "match_all": true } - ] - }, - { "keys": ["tab"], "command": "indent_list_item", "context": - [ - { "key": "selection_empty", "operator": "equal", "operand": true, "match_all": true }, - { "key": "preceding_text", "operator": "regex_contains", "operand": "^\\s*(>\\s*)?[*+\\-]\\s+$", "match_all": true }, - { "key": "following_text", "operator": "regex_contains", "operand": "^$", "match_all": true }, - { "key": "selector", "operator": "equal", "operand": "text.html.markdown", "match_all": true }, - { "key": "selector", "operator": "not_equal", "operand": "markup.raw", "match_all": true } - ] - }, - { "keys": ["tab"], "command": "indent_list_multiitem", "context": - [ - { "key": "selection_empty", "operator": "equal", "operand": false, "match_all": true }, - { "key": "selector", "operator": "equal", "operand": "text.html.markdown", "match_all": true }, - { "key": "selector", "operator": "equal", "operand": "markup.list", "match_all": true } - ] - }, - { "keys": ["shift+tab"], "command": "indent_list_item", "args": {"reverse": true}, "context": - [ - { "key": "selection_empty", "operator": "equal", "operand": true, "match_all": true }, - { "key": "preceding_text", "operator": "regex_contains", "operand": "^\\s*(>\\s*)?[*+\\-]\\s+$", "match_all": true }, - { "key": "following_text", "operator": "regex_contains", "operand": "^$", "match_all": true }, - { "key": "selector", "operator": "equal", "operand": "text.html.markdown", "match_all": true }, - { "key": "selector", "operator": "not_equal", "operand": "markup.raw", "match_all": true } - ] - }, - { "keys": ["shift+tab"], "command": "indent_list_multiitem", "args": {"reverse": true}, "context": - [ - { "key": "selection_empty", "operator": "equal", "operand": false, "match_all": true }, - { "key": "selector", "operator": "equal", "operand": "text.html.markdown", "match_all": true }, - { "key": "selector", "operator": "equal", "operand": "markup.list", "match_all": true } - ] - }, - { "keys": ["_"], "command": "insert_snippet", "args": {"contents": "_$0_"}, "context": - [ - { "key": "setting.auto_match_enabled", "operator": "equal", "operand": true }, - { "key": "selection_empty", "operator": "equal", "operand": true, "match_all": true }, - { "key": "following_text", "operator": "regex_contains", "operand": "^(?:\t| |\\)|]|\\}|$)", "match_all": true }, - { "key": "preceding_text", "operator": "not_regex_contains", "operand": "['a-zA-Z0-9_]$", "match_all": true }, - { "key": "eol_selector", "operator": "not_equal", "operand": "string.quoted.single", "match_all": true }, - { "key": "selector", "operator": "equal", "operand": "text.html.markdown", "match_all": true }, - { "key": "selector", "operator": "not_equal", "operand": "markup.raw", "match_all": true } - ] - }, - { "keys": ["_"], "command": "insert_snippet", "args": {"contents": "_${0:$SELECTION}_"}, "context": - [ - { "key": "setting.auto_match_enabled", "operator": "equal", "operand": true }, - { "key": "selection_empty", "operator": "equal", "operand": false, "match_all": true }, - { "key": "selector", "operator": "equal", "operand": "text.html.markdown", "match_all": true }, - { "key": "selector", "operator": "not_equal", "operand": "markup.raw", "match_all": true } - ] - }, - { "keys": ["_"], "command": "run_macro_file", "args": {"file": "Packages/MarkdownEditing/macros/Skip Closing Character.sublime-macro"}, "context": - [ - { "key": "selection_empty", "operator": "equal", "operand": true, "match_all": true }, - { "key": "following_text", "operator": "regex_contains", "operand": "^_", "match_all": true }, - { "key": "selector", "operator": "equal", "operand": "text.html.markdown", "match_all": true }, - { "key": "selector", "operator": "not_equal", "operand": "markup.raw", "match_all": true } - ] - }, - { "keys": ["backspace"], "command": "run_macro_file", "args": {"file": "Packages/Default/Delete Left Right.sublime-macro"}, "context": - [ - { "key": "setting.auto_match_enabled", "operator": "equal", "operand": true }, - { "key": "selection_empty", "operator": "equal", "operand": true, "match_all": true }, - { "key": "preceding_text", "operator": "regex_contains", "operand": "_$", "match_all": true }, - { "key": "following_text", "operator": "regex_contains", "operand": "^_", "match_all": true }, - { "key": "selector", "operator": "equal", "operand": "text.html.markdown", "match_all": true }, - { "key": "selector", "operator": "not_equal", "operand": "markup.raw", "match_all": true } - ] - }, - { "keys": [" "], "command": "run_macro_file", "args": {"file": "Packages/MarkdownEditing/macros/Start List Item.sublime-macro"}, "context": - [ - { "key": "setting.auto_match_enabled", "operator": "equal", "operand": true }, - { "key": "selection_empty", "operator": "equal", "operand": true, "match_all": true }, - { "key": "preceding_text", "operator": "regex_contains", "operand": "\\_$", "match_all": true }, - { "key": "following_text", "operator": "regex_contains", "operand": "^\\_", "match_all": true }, - { "key": "selector", "operator": "equal", "operand": "text.html.markdown", "match_all": true }, - { "key": "selector", "operator": "not_equal", "operand": "markup.raw", "match_all": true } - ] - }, - { "keys": ["`"], "command": "insert_snippet", "args": {"contents": "`$0`"}, "context": - [ - { "key": "setting.auto_match_enabled", "operator": "equal", "operand": true }, - { "key": "selection_empty", "operator": "equal", "operand": true, "match_all": true }, - { "key": "following_text", "operator": "regex_contains", "operand": "^(?:\t| |\\)|]|\\}|$)", "match_all": true }, - { "key": "preceding_text", "operator": "not_regex_contains", "operand": "['a-zA-Z0-9_`]$", "match_all": true }, - { "key": "eol_selector", "operator": "not_equal", "operand": "string.quoted.single", "match_all": true }, - { "key": "selector", "operator": "equal", "operand": "text.html.markdown", "match_all": true } - ] - }, - { "keys": ["`"], "command": "insert_snippet", "args": {"contents": "`${0:$SELECTION}`"}, "context": - [ - { "key": "setting.auto_match_enabled", "operator": "equal", "operand": true }, - { "key": "selection_empty", "operator": "equal", "operand": false, "match_all": true }, - { "key": "selector", "operator": "equal", "operand": "text.html.markdown", "match_all": true } - ] - }, - { "keys": ["`"], "command": "run_macro_file", "args": {"file": "Packages/MarkdownEditing/macros/Skip Closing Character.sublime-macro"}, "context": - [ - { "key": "selection_empty", "operator": "equal", "operand": true, "match_all": true }, - { "key": "following_text", "operator": "regex_contains", "operand": "^`", "match_all": true }, - { "key": "selector", "operator": "equal", "operand": "text.html.markdown", "match_all": true } - ] - }, - { "keys": ["~"], "command": "insert_snippet", "args": {"contents": "~~${0:$SELECTION}~~"}, "context": - [ - { "key": "setting.auto_match_enabled", "operator": "equal", "operand": true }, - { "key": "selection_empty", "operator": "equal", "operand": false, "match_all": true }, - { "key": "selector", "operator": "equal", "operand": "text.html.markdown", "match_all": true }, - { "key": "selector", "operator": "not_equal", "operand": "markup.raw", "match_all": true } - ] - }, - { "keys": ["backspace"], "command": "run_macro_file", "args": {"file": "Packages/Default/Delete Left Right.sublime-macro"}, "context": - [ - { "key": "setting.auto_match_enabled", "operator": "equal", "operand": true }, - { "key": "selection_empty", "operator": "equal", "operand": true, "match_all": true }, - { "key": "preceding_text", "operator": "regex_contains", "operand": "`$", "match_all": true }, - { "key": "following_text", "operator": "regex_contains", "operand": "^`", "match_all": true }, - { "key": "selector", "operator": "equal", "operand": "text.html.markdown", "match_all": true } - ] - }, - // Bold on Super + Alt + B - { "keys": ["super+alt+b"], "command": "run_macro_file", "args": {"file": "Packages/MarkdownEditing/macros/Transform Word - Bold.sublime-macro"}, "context": - [ - { "key": "selection_empty", "operator": "equal", "operand": true, "match_all": true }, - { "key": "selector", "operator": "equal", "operand": "text.html.markdown", "match_all": true } - ] - }, - { "keys": ["super+alt+b"], "command": "insert_snippet", "args": {"contents": "${MD_BOLD_MARKER}$1${MD_BOLD_MARKER}"}, "context": - [ - { "key": "setting.auto_match_enabled", "operator": "equal", "operand": true }, - { "key": "selection_empty", "operator": "equal", "operand": true, "match_all": true }, - { "key": "following_text", "operator": "regex_contains", "operand": "^(?:\t| |\\)|]|\\}|$)", "match_all": true }, - { "key": "preceding_text", "operator": "not_regex_contains", "operand": "['a-zA-Z0-9_]$", "match_all": true }, - { "key": "eol_selector", "operator": "not_equal", "operand": "string.quoted.single", "match_all": true }, - { "key": "selector", "operator": "equal", "operand": "text.html.markdown", "match_all": true } - ] - }, - { "keys": ["super+alt+b"], "command": "insert_snippet", "args": {"contents": "${MD_BOLD_MARKER}${SELECTION/(^[\\*_]*|[\\*_]*$)//g}${MD_BOLD_MARKER}"}, "context": - [ - { "key": "setting.auto_match_enabled", "operator": "equal", "operand": true }, - { "key": "selection_empty", "operator": "equal", "operand": false, "match_all": true }, - { "key": "selector", "operator": "equal", "operand": "text.html.markdown", "match_all": true } - ] - }, - // italics on Super + Alt + I - { "keys": ["super+alt+i"], "command": "run_macro_file", "args": {"file": "Packages/MarkdownEditing/macros/Transform Word - Italic.sublime-macro"}, "context": - [ - { "key": "selection_empty", "operator": "equal", "operand": true, "match_all": true }, - { "key": "selector", "operator": "equal", "operand": "text.html.markdown", "match_all": true } - ] - }, - { "keys": ["super+alt+i"], "command": "insert_snippet", "args": {"contents": "${MD_ITALIC_MARKER}$0${MD_ITALIC_MARKER}"}, "context": - [ - { "key": "setting.auto_match_enabled", "operator": "equal", "operand": true }, - { "key": "selection_empty", "operator": "equal", "operand": true, "match_all": true }, - { "key": "following_text", "operator": "regex_contains", "operand": "^(?:\t| |\\)|]|\\}|$)", "match_all": true }, - { "key": "preceding_text", "operator": "not_regex_contains", "operand": "['a-zA-Z0-9_]$", "match_all": true }, - { "key": "eol_selector", "operator": "not_equal", "operand": "string.quoted.single", "match_all": true }, - { "key": "selector", "operator": "equal", "operand": "text.html.markdown", "match_all": true } - ] - }, - { "keys": ["super+alt+i"], "command": "insert_snippet", "args": {"contents": "${MD_ITALIC_MARKER}${SELECTION/(^[\\*_]*|[\\*_]*$)//g}${MD_ITALIC_MARKER}"}, "context": - [ - { "key": "setting.auto_match_enabled", "operator": "equal", "operand": true }, - { "key": "selection_empty", "operator": "equal", "operand": false, "match_all": true }, - { "key": "selector", "operator": "equal", "operand": "text.html.markdown", "match_all": true } - ] - }, + // Fix smart expand selection + // see: https://github.com/sublimehq/sublime_text/issues/4125 + { "keys": ["super+shift+a"], "command": "expand_selection", "args": {"to": "smart"}, "context": + [ + { "key": "selector", "operand": "text.html.markdown - text.html.markdown text.html - text.html.markdown text.xml - text.html.markdown meta.disable-markdown", "match_all": true } + ] + }, - // Unbold on Super + Alt + B if already bold - { "keys": ["super+alt+b"], "command": "insert_snippet", "args": {"contents": "${SELECTION/(^[\\*_]{2}|[\\*_]{2}$)//g}"}, "context": - [ - { "key": "selection_empty", "operator": "equal", "operand": false, "match_all": true }, - { "key": "text", "operator": "regex_match", "operand": "^[*_]{2}.*[*_]{2}$", "match_all": true }, - { "key": "selector", "operator": "equal", "operand": "text.html.markdown", "match_all": true } - ] - }, - { "keys": ["super+alt+b"], "command": "run_macro_file", "args": {"file": "Packages/MarkdownEditing/macros/Transform Word - Unbold Unitalicize.sublime-macro"}, "context": - [ - { "key": "selection_empty", "operator": "equal", "operand": true, "match_all": true }, - { "key": "selector", "operator": "equal", "operand": "text.html.markdown markup.bold.markdown", "match_all": true } - ] - }, - { "keys": ["super+alt+b"], "command": "run_macro_file", "args": {"file": "Packages/MarkdownEditing/macros/Transform Word - Unbold Unitalicize.sublime-macro"}, "context": - [ - { "key": "selection_empty", "operator": "equal", "operand": true, "match_all": true }, - { "key": "preceding_text", "operator": "regex_contains", "operand": "\\b__+\\S+__+$", "match_all": true }, - { "key": "selector", "operator": "equal", "operand": "text.html.markdown", "match_all": true } - ] - }, + // + // Auto-Pairing Astersisks + // - // Unitalicize on Super + Alt + I if already italic - { "keys": ["super+alt+i"], "command": "insert_snippet", "args": {"contents": "${SELECTION/(^[\\*_]|[\\*_]$)//g}"}, "context": - [ - { "key": "selection_empty", "operator": "equal", "operand": false, "match_all": true }, - { "key": "text", "operator": "regex_match", "operand": "^[*_].*[*_]$", "match_all": true }, - { "key": "selector", "operator": "equal", "operand": "text.html.markdown", "match_all": true } - ] - }, - { "keys": ["super+alt+i"], "command": "run_macro_file", "args": {"file": "Packages/MarkdownEditing/macros/Transform Word - Unbold Unitalicize.sublime-macro"}, "context": - [ - { "key": "selection_empty", "operator": "equal", "operand": true, "match_all": true }, - { "key": "selector", "operator": "equal", "operand": "text.html.markdown markup.italic.markdown", "match_all": true } - ] - }, - { "keys": ["super+alt+i"], "command": "run_macro_file", "args": {"file": "Packages/MarkdownEditing/macros/Transform Word - Unbold Unitalicize.sublime-macro"}, "context": - [ - { "key": "selection_empty", "operator": "equal", "operand": true, "match_all": true }, - { "key": "preceding_text", "operator": "regex_contains", "operand": "\\b_(?!_)\\S+_$", "match_all": true }, - { "key": "selector", "operator": "equal", "operand": "text.html.markdown", "match_all": true } - ] - }, + { "keys": ["*"], "command": "insert_snippet", "args": {"contents": "*$0*"}, "context": + [ + { "key": "selector", "operator": "equal", "operand": "text.html.markdown - meta.frontmatter - meta.disable-markdown - markup.raw - markup.kbd", "match_all": true }, + { "key": "setting.auto_match_enabled", "operator": "equal", "operand": true }, + { "key": "selection_empty", "operator": "equal", "operand": true, "match_all": true }, + { "key": "eol_selector", "operator": "not_equal", "operand": "string.quoted.single", "match_all": true }, + { "key": "preceding_text", "operator": "not_regex_contains", "operand": "['a-zA-Z0-9_*]$", "match_all": true }, + { "key": "following_text", "operator": "regex_contains", "operand": "^(?:\t| |\\)|]|\\}|$)", "match_all": true } + ] + }, + { "keys": ["*"], "command": "insert_snippet", "args": {"contents": "*${0:$SELECTION}*"}, "context": + [ + { "key": "selector", "operator": "equal", "operand": "text.html.markdown - meta.frontmatter - meta.disable-markdown - markup.raw - markup.kbd", "match_all": true }, + { "key": "setting.auto_match_enabled", "operator": "equal", "operand": true }, + { "key": "selection_empty", "operator": "equal", "operand": false, "match_all": true } + ] + }, + { "keys": ["*"], "command": "move", "args": {"by": "characters", "forward": true}, "context": + [ + { "key": "selector", "operator": "equal", "operand": "text.html.markdown - meta.frontmatter - meta.disable-markdown - markup.raw - markup.kbd", "match_all": true }, + { "key": "selection_empty", "operator": "equal", "operand": true, "match_all": true }, + { "key": "following_text", "operator": "regex_contains", "operand": "^\\*", "match_all": true } + ] + }, + { "keys": ["backspace"], "command": "run_macro_file", "args": {"file": "Packages/Default/Delete Left Right.sublime-macro"}, "context": + [ + { "key": "selector", "operator": "equal", "operand": "text.html.markdown - meta.frontmatter - meta.disable-markdown - markup.raw - markup.kbd", "match_all": true }, + { "key": "setting.auto_match_enabled", "operator": "equal", "operand": true }, + { "key": "selection_empty", "operator": "equal", "operand": true, "match_all": true }, + { "key": "preceding_text", "operator": "regex_contains", "operand": "\\*$", "match_all": true }, + { "key": "following_text", "operator": "regex_contains", "operand": "^\\*", "match_all": true } + ] + }, + { "keys": [" "], "command": "run_macro_file", "args": {"file": "Packages/MarkdownEditing/macros/Start List Item.sublime-macro"}, "context": + [ + { "key": "selector", "operator": "equal", "operand": "text.html.markdown - meta.frontmatter - meta.disable-markdown - markup.raw - markup.kbd", "match_all": true }, + { "key": "setting.auto_match_enabled", "operator": "equal", "operand": true }, + { "key": "selection_empty", "operator": "equal", "operand": true, "match_all": true }, + { "key": "preceding_text", "operator": "regex_contains", "operand": "\\*$", "match_all": true }, + { "key": "following_text", "operator": "regex_contains", "operand": "^\\*", "match_all": true } + ] + }, + { "keys": ["tab"], "command": "run_macro_file", "args": {"file": "Packages/MarkdownEditing/macros/Start List Item Tab.sublime-macro"}, "context": + [ + { "key": "selector", "operator": "equal", "operand": "text.html.markdown - meta.frontmatter - meta.disable-markdown - markup.raw - markup.kbd", "match_all": true }, + { "key": "setting.auto_match_enabled", "operator": "equal", "operand": true }, + { "key": "selection_empty", "operator": "equal", "operand": true, "match_all": true }, + { "key": "preceding_text", "operator": "regex_contains", "operand": "\\*$", "match_all": true }, + { "key": "following_text", "operator": "regex_contains", "operand": "^\\*", "match_all": true } + ] + }, - // Headers - { "keys": ["#"], "command": "insert_snippet", "args": {"contents": "#${0: ${SELECTION/(^ | $)//g} }#"}, "context": - [ - { "key": "selection_empty", "operator": "equal", "operand": false, "match_all": true }, - { "key": "selector", "operator": "equal", "operand": "text.html.markdown", "match_all": true }, - { "key": "preceding_text", "operator": "not_regex_contains", "operand": "#{6}", "match_all": true }, - { "key": "setting.mde.match_header_hashes", "operator": "equal", "operand": true }, - { "key": "selector", "operator": "not_equal", "operand": "markup.raw", "match_all": true } - ] - }, - { "keys": ["#"], "command": "insert_snippet", "args": {"contents": "#${0: ${SELECTION/(^ | $)//g}}"}, "context": - [ - { "key": "selection_empty", "operator": "equal", "operand": false, "match_all": true }, - { "key": "selector", "operator": "equal", "operand": "text.html.markdown", "match_all": true }, - { "key": "preceding_text", "operator": "not_regex_contains", "operand": "#{6}", "match_all": true }, - { "key": "setting.mde.match_header_hashes", "operator": "equal", "operand": false }, - { "key": "selector", "operator": "not_equal", "operand": "markup.raw", "match_all": true } - ] - }, - { "keys": ["#"], "command": "run_macro_file", "args": {"file": "Packages/MarkdownEditing/macros/Padded Headline.sublime-macro"}, "context": - [ - { "key": "selection_empty", "operator": "equal", "operand": false, "match_all": true }, - { "key": "selector", "operator": "equal", "operand": "text.html.markdown", "match_all": true }, - { "key": "preceding_text", "operator": "regex_contains", "operand": "#{6}", "match_all": true }, - { "key": "following_text", "operator": "regex_contains", "operand": "#+", "match_all": true }, - { "key": "setting.mde.match_header_hashes", "operator": "equal", "operand": true }, - { "key": "selector", "operator": "not_equal", "operand": "markup.raw", "match_all": true } - ] - }, - { "keys": ["#"], "command": "run_macro_file", "args": {"file": "Packages/MarkdownEditing/macros/Padded Headline.sublime-macro"}, "context": - [ - { "key": "selection_empty", "operator": "equal", "operand": false, "match_all": true }, - { "key": "selector", "operator": "equal", "operand": "text.html.markdown", "match_all": true }, - { "key": "preceding_text", "operator": "regex_contains", "operand": "#{6}", "match_all": true }, - { "key": "setting.mde.match_header_hashes", "operator": "equal", "operand": false }, - { "key": "selector", "operator": "not_equal", "operand": "markup.raw", "match_all": true } - ] - }, - { "keys": ["enter"], "command": "insert_snippet", "args": {"contents": " ${TM_CURRENT_LINE/(#+?)[^#].*$/$1\n/}"}, "context": - [ - { "key": "selector", "operator": "equal", "operand": "text.html.markdown", "match_all": true }, - { "key": "preceding_text", "operator": "regex_contains", "operand": "^#+\\s+[^#]", "match_all": true }, - { "key": "preceding_text", "operator": "not_regex_contains", "operand": "#+$", "match_all": true }, - { "key": "following_text", "operator": "regex_contains", "operand": "^\\s*$", "match_all": true }, - { "key": "setting.mde.match_header_hashes", "operator": "equal", "operand": true }, - { "key": "auto_complete_visible", "operator": "equal", "operand": false }, - { "key": "selector", "operator": "not_equal", "operand": "markup.raw", "match_all": true } - ] - }, - // Extend lists - { "keys": ["enter"], "command": "insert_snippet", "args": {"contents": "${TM_CURRENT_LINE/^(\\s*([*\\-+])(\\s+)).*/\n$2$3/}"}, "context": - [ - { "key": "selector", "operator": "equal", "operand": "text.html.markdown", "match_all": true }, - { "key": "preceding_text", "operator": "regex_contains", "operand": "^(\\s*([*\\-+])\\s+)\\S.*", "match_all": true }, - { "key": "auto_complete_visible", "operator": "equal", "operand": false }, - { "key": "selector", "operator": "not_equal", "operand": "markup.raw", "match_all": true } - ] - }, - // Extend lists with GFM tasks - { "keys": ["enter"], "command": "insert_snippet", "args": {"contents": "${TM_CURRENT_LINE/^(\\s*([*\\-+])(\\s+)\\[[ x]\\](\\s+)).*/\n$2$3[ ]$4/}"}, "context": - [ - { "key": "selector", "operator": "equal", "operand": "text.html.markdown", "match_all": true }, - { "key": "preceding_text", "operator": "regex_contains", "operand": "^(\\s*([*\\-+])\\s+)\\[[ x]\\]\\s+\\S.*", "match_all": true }, - { "key": "auto_complete_visible", "operator": "equal", "operand": false }, - { "key": "selector", "operator": "not_equal", "operand": "markup.raw", "match_all": true } - ] - }, - // Extend Numbered Lists - { "keys": ["enter"], "command": "number_list", "context": - [ - { "key": "selector", "operator": "equal", "operand": "text.html.markdown", "match_all": true }, - { "key": "preceding_text", "operator": "regex_contains", "operand": "^(\\s*(\\d+\\.)\\s+)\\S.*", "match_all": true }, - { "key": "auto_complete_visible", "operator": "equal", "operand": false }, - { "key": "selector", "operator": "not_equal", "operand": "markup.raw", "match_all": true } - ] - }, - // Extend Numbered Reference - { "keys": ["enter"], "command": "number_list_reference", "context": - [ - { "key": "selector", "operator": "equal", "operand": "text.html.markdown", "match_all": true }, - { "key": "preceding_text", "operator": "regex_contains", "operand": "^(\\s*\\[(\\d+)\\]:\\s*)\\S.*", "match_all": true }, - { "key": "auto_complete_visible", "operator": "equal", "operand": false }, - { "key": "selector", "operator": "not_equal", "operand": "markup.raw", "match_all": true } - ] - }, - // Remove empty list item - { "keys": ["enter"], "command": "run_macro_file", "args": {"file": "Packages/MarkdownEditing/macros/Remove Empty List Item.sublime-macro"}, "context": - [ - { "key": "selector", "operator": "equal", "operand": "text.html.markdown", "match_all": true }, - { "key": "preceding_text", "operator": "regex_contains", "operand": "^(\\s*(\\[\\d+\\]:|[*\\-+]|\\d+\\.)\\s+)$", "match_all": true }, - { "key": "following_text", "operator": "regex_contains", "operand": "^\\s*$", "match_all": true }, - { "key": "auto_complete_visible", "operator": "equal", "operand": false }, - { "key": "selector", "operator": "not_equal", "operand": "markup.raw", "match_all": true } - ] - }, - // Extend blockquote - { "keys": ["enter"], "command": "insert_snippet", "args": {"contents": "${TM_CURRENT_LINE/^(\\s*((>+\\s+)+([*\\-+]\\s+)?)).*/\n$2/}"}, "context": - [ - { "key": "selector", "operator": "equal", "operand": "text.html.markdown", "match_all": true }, - { "key": "preceding_text", "operator": "regex_contains", "operand": "^\\s*>+\\s+", "match_all": true }, - { "key": "auto_complete_visible", "operator": "equal", "operand": false } - ] - }, - // Convert to blockquote - { "keys": [">"], "command": "run_macro_file", "args": {"file": "Packages/MarkdownEditing/macros/Convert to Blockquote.sublime-macro"}, "context": - [ - { "key": "selection_empty", "operator": "equal", "operand": false, "match_all": true }, - { "key": "selector", "operator": "equal", "operand": "text.html.markdown", "match_all": true }, - { "key": "selector", "operator": "not_equal", "operand": "markup.raw", "match_all": true } - ] - }, - { "keys": ["tab"], "command": "complete_underlined_header", "context": - [ - { "key": "selector", "operator": "equal", "operand": "text.html.markdown", "match_all": true }, - { "key": "selection_empty", "operator": "equal", "operand": true, "match_all": true }, - { "key": "auto_complete_visible", "operator": "equal", "operand": false, "match_all": true }, - { "key": "preceding_text", "operator": "regex_contains", "operand": "^\\-+$|^\\=+$", "match_all": true }, - { "key": "selector", "operator": "not_equal", "operand": "markup.raw", "match_all": true } - ] - }, - // Surround with <> on URLs, regex copied from https://mathiasbynens.be/demo/url-regex, @diegoperini (502 chars) - { "keys": ["<"], "command": "insert_snippet", "args": {"contents": "<${0:$SELECTION}>"}, "context": - [ - { "key": "setting.auto_match_enabled", "operator": "equal", "operand": true }, - { "key": "selection_empty", "operator": "equal", "operand": false, "match_all": true }, - { "key": "selector", "operator": "equal", "operand": "text.html.markdown", "match_all": true }, - { "key": "text", "operator": "regex_match", "operand": "(?:(?:https?|ftp)://)(?:\\S+(?::\\S*)?@)?(?:(?!10(?:\\.\\d{1,3}){3})(?!127(?:\\.\\d{1,3}){3})(?!169\\.254(?:\\.\\d{1,3}){2})(?!192\\.168(?:\\.\\d{1,3}){2})(?!172\\.(?:1[6-9]|2\\d|3[0-1])(?:\\.\\d{1,3}){2})(?:[1-9]\\d?|1\\d\\d|2[01]\\d|22[0-3])(?:\\.(?:1?\\d{1,2}|2[0-4]\\d|25[0-5])){2}(?:\\.(?:[1-9]\\d?|1\\d\\d|2[0-4]\\d|25[0-4]))|(?:(?:[a-z\\x{00a1}-\\x{ffff}0-9]+-?)*[a-z\\x{00a1}-\\x{ffff}0-9]+)(?:\\.(?:[a-z\\x{00a1}-\\x{ffff}0-9]+-?)*[a-z\\x{00a1}-\\x{ffff}0-9]+)*(?:\\.(?:[a-z\\x{00a1}-\\x{ffff}]{2,})))(?::\\d{2,5})?(?:/[^\\s]*)?", "match_all": true } - ] - }, + // + // Auto-Pairing Underscore + // - // inline image insertion - { "keys": ["super+shift+k"], "command": "reference_new_inline_image", "context": - [ - { "key": "setting.mde.keymap_disable.reference_new_inline_image", "operator": "not_equal", "operand": true }, - { "key": "selector", "operator": "equal", "operand": "text.html.markdown", "match_all": true } - ] - }, - // modify [] pairing so that selection is removed after pairing, ready for [] or () - { "keys": ["["], "command": "insert_snippet", "args": {"contents": "[$SELECTION]$0"}, "context": - [ - { "key": "setting.auto_match_enabled", "operator": "equal", "operand": true }, - { "key": "selection_empty", "operator": "equal", "operand": false, "match_all": true }, - { "key": "selector", "operator": "equal", "operand": "text.html.markdown", "match_all": true } - ] - }, - // run paste as link command on selected text - { "keys": ["super+alt+v"], "command": "reference_new_inline_link", "context": - [ - { "key": "setting.mde.keymap_disable.reference_new_inline_link", "operator": "not_equal", "operand": true }, - { "key": "selector", "operator": "equal", "operand": "text.html.markdown", "match_all": true } - ] - }, - { "keys": ["super+alt+r"], "command": "reference_new_reference", "context": - [ - { "key": "setting.mde.keymap_disable.reference_new_reference", "operator": "not_equal", "operand": true }, - { "key": "selector", "operator": "equal", "operand": "text.html.markdown", "match_all": true } - ] - }, - { "keys": ["super+ctrl+shift+l"], "command": "reference_jump", "context": - [ - { "key": "setting.mde.keymap_disable.reference_jump", "operator": "not_equal", "operand": true }, - { "key": "selector", "operator": "equal", "operand": "text.html.markdown", "match_all": true } - ] - }, - // Set Headers Levels With Shortcuts - { "keys": ["super+ctrl+1"], "command": "insert_snippet", "args": {"contents": "# $0"}, "context": - [ - { "key": "setting.auto_match_enabled", "operator": "equal", "operand": true }, - { "key": "selection_empty", "operator": "equal", "operand": true, "match_all": true }, - { "key": "following_text", "operator": "regex_contains", "operand": "^(?:\t| |\\)|]|\\}|$)", "match_all": true }, - { "key": "preceding_text", "operator": "not_regex_contains", "operand": "['a-zA-Z0-9_]$", "match_all": true }, - { "key": "eol_selector", "operator": "not_equal", "operand": "string.quoted.single", "match_all": true }, - { "key": "selector", "operator": "equal", "operand": "text.html.markdown", "match_all": true } - ] - }, - { "keys": ["super+ctrl+1"], "command": "insert_snippet", "args": {"contents": "#${0: ${SELECTION/(^( +)?(#+)?\\s*|\\s*(#+)?( +)?$)//g}}$1"}, "context": - [ - { "key": "setting.auto_match_enabled", "operator": "equal", "operand": true }, - { "key": "setting.mde.match_header_hashes", "operator": "equal", "operand": false }, - { "key": "selection_empty", "operator": "equal", "operand": false, "match_all": true }, - { "key": "selector", "operator": "equal", "operand": "text.html.markdown", "match_all": true } - ] - }, - { "keys": ["super+ctrl+1"], "command": "insert_snippet", "args": {"contents": "#${0: ${SELECTION/(^( +)?(#+)?\\s*|\\s*(#+)?( +)?$)//g} }#$1"}, "context": - [ - { "key": "setting.auto_match_enabled", "operator": "equal", "operand": true }, - { "key": "setting.mde.match_header_hashes", "operator": "equal", "operand": true }, - { "key": "selection_empty", "operator": "equal", "operand": false, "match_all": true }, - { "key": "selector", "operator": "equal", "operand": "text.html.markdown", "match_all": true } - ] - }, - { "keys": ["super+ctrl+2"], "command": "insert_snippet", "args": {"contents": "## $0"}, "context": - [ - { "key": "setting.auto_match_enabled", "operator": "equal", "operand": true }, - { "key": "selection_empty", "operator": "equal", "operand": true, "match_all": true }, - { "key": "following_text", "operator": "regex_contains", "operand": "^(?:\t| |\\)|]|\\}|$)", "match_all": true }, - { "key": "preceding_text", "operator": "not_regex_contains", "operand": "['a-zA-Z0-9_]$", "match_all": true }, - { "key": "eol_selector", "operator": "not_equal", "operand": "string.quoted.single", "match_all": true }, - { "key": "selector", "operator": "equal", "operand": "text.html.markdown", "match_all": true } - ] - }, - { "keys": ["super+ctrl+2"], "command": "insert_snippet", "args": {"contents": "##${0: ${SELECTION/(^( +)?(#+)?\\s*|\\s*(#+)?( +)?$)//g}}$1"}, "context": - [ - { "key": "setting.auto_match_enabled", "operator": "equal", "operand": true }, - { "key": "setting.mde.match_header_hashes", "operator": "equal", "operand": false }, - { "key": "selection_empty", "operator": "equal", "operand": false, "match_all": true }, - { "key": "selector", "operator": "equal", "operand": "text.html.markdown", "match_all": true } - ] - }, - { "keys": ["super+ctrl+2"], "command": "insert_snippet", "args": {"contents": "##${0: ${SELECTION/(^( +)?(#+)?\\s*|\\s*(#+)?( +)?$)//g} }##$1"}, "context": - [ - { "key": "setting.auto_match_enabled", "operator": "equal", "operand": true }, - { "key": "setting.mde.match_header_hashes", "operator": "equal", "operand": true }, - { "key": "selection_empty", "operator": "equal", "operand": false, "match_all": true }, - { "key": "selector", "operator": "equal", "operand": "text.html.markdown", "match_all": true } - ] - }, - { "keys": ["super+ctrl+3"], "command": "insert_snippet", "args": {"contents": "### $0"}, "context": - [ - { "key": "setting.auto_match_enabled", "operator": "equal", "operand": true }, - { "key": "selection_empty", "operator": "equal", "operand": true, "match_all": true }, - { "key": "following_text", "operator": "regex_contains", "operand": "^(?:\t| |\\)|]|\\}|$)", "match_all": true }, - { "key": "preceding_text", "operator": "not_regex_contains", "operand": "['a-zA-Z0-9_]$", "match_all": true }, - { "key": "eol_selector", "operator": "not_equal", "operand": "string.quoted.single", "match_all": true }, - { "key": "selector", "operator": "equal", "operand": "text.html.markdown", "match_all": true } - ] - }, - { "keys": ["super+ctrl+3"], "command": "insert_snippet", "args": {"contents": "###${0: ${SELECTION/(^( +)?(#+)?\\s*|\\s*(#+)?( +)?$)//g}}$1"}, "context": - [ - { "key": "setting.auto_match_enabled", "operator": "equal", "operand": true }, - { "key": "setting.mde.match_header_hashes", "operator": "equal", "operand": false }, - { "key": "selection_empty", "operator": "equal", "operand": false, "match_all": true }, - { "key": "selector", "operator": "equal", "operand": "text.html.markdown", "match_all": true } - ] - }, - { "keys": ["super+ctrl+3"], "command": "insert_snippet", "args": {"contents": "###${0: ${SELECTION/(^( +)?(#+)?\\s*|\\s*(#+)?( +)?$)//g} }###$1"}, "context": - [ - { "key": "setting.auto_match_enabled", "operator": "equal", "operand": true }, - { "key": "setting.mde.match_header_hashes", "operator": "equal", "operand": true }, - { "key": "selection_empty", "operator": "equal", "operand": false, "match_all": true }, - { "key": "selector", "operator": "equal", "operand": "text.html.markdown", "match_all": true } - ] - }, - { "keys": ["super+ctrl+4"], "command": "insert_snippet", "args": {"contents": "#### $0"}, "context": - [ - { "key": "setting.auto_match_enabled", "operator": "equal", "operand": true }, - { "key": "selection_empty", "operator": "equal", "operand": true, "match_all": true }, - { "key": "following_text", "operator": "regex_contains", "operand": "^(?:\t| |\\)|]|\\}|$)", "match_all": true }, - { "key": "preceding_text", "operator": "not_regex_contains", "operand": "['a-zA-Z0-9_]$", "match_all": true }, - { "key": "eol_selector", "operator": "not_equal", "operand": "string.quoted.single", "match_all": true }, - { "key": "selector", "operator": "equal", "operand": "text.html.markdown", "match_all": true } - ] - }, - { "keys": ["super+ctrl+4"], "command": "insert_snippet", "args": {"contents": "####${0: ${SELECTION/(^( +)?(#+)?\\s*|\\s*(#+)?( +)?$)//g}}$1"}, "context": - [ - { "key": "setting.auto_match_enabled", "operator": "equal", "operand": true }, - { "key": "setting.mde.match_header_hashes", "operator": "equal", "operand": false }, - { "key": "selection_empty", "operator": "equal", "operand": false, "match_all": true }, - { "key": "selector", "operator": "equal", "operand": "text.html.markdown", "match_all": true } - ] - }, - { "keys": ["super+ctrl+4"], "command": "insert_snippet", "args": {"contents": "####${0: ${SELECTION/(^( +)?(#+)?\\s*|\\s*(#+)?( +)?$)//g} }####$1"}, "context": - [ - { "key": "setting.auto_match_enabled", "operator": "equal", "operand": true }, - { "key": "setting.mde.match_header_hashes", "operator": "equal", "operand": true }, - { "key": "selection_empty", "operator": "equal", "operand": false, "match_all": true }, - { "key": "selector", "operator": "equal", "operand": "text.html.markdown", "match_all": true } - ] - }, - { "keys": ["super+ctrl+5"], "command": "insert_snippet", "args": {"contents": "##### $0"}, "context": - [ - { "key": "setting.auto_match_enabled", "operator": "equal", "operand": true }, - { "key": "selection_empty", "operator": "equal", "operand": true, "match_all": true }, - { "key": "following_text", "operator": "regex_contains", "operand": "^(?:\t| |\\)|]|\\}|$)", "match_all": true }, - { "key": "preceding_text", "operator": "not_regex_contains", "operand": "['a-zA-Z0-9_]$", "match_all": true }, - { "key": "eol_selector", "operator": "not_equal", "operand": "string.quoted.single", "match_all": true }, - { "key": "selector", "operator": "equal", "operand": "text.html.markdown", "match_all": true } - ] - }, - { "keys": ["super+ctrl+5"], "command": "insert_snippet", "args": {"contents": "#####${0: ${SELECTION/(^( +)?(#+)?\\s*|\\s*(#+)?( +)?$)//g}}$1"}, "context": - [ - { "key": "setting.auto_match_enabled", "operator": "equal", "operand": true }, - { "key": "setting.mde.match_header_hashes", "operator": "equal", "operand": false }, - { "key": "selection_empty", "operator": "equal", "operand": false, "match_all": true }, - { "key": "selector", "operator": "equal", "operand": "text.html.markdown", "match_all": true } - ] - }, - { "keys": ["super+ctrl+5"], "command": "insert_snippet", "args": {"contents": "#####${0: ${SELECTION/(^( +)?(#+)?\\s*|\\s*(#+)?( +)?$)//g} }#####$1"}, "context": - [ - { "key": "setting.auto_match_enabled", "operator": "equal", "operand": true }, - { "key": "setting.mde.match_header_hashes", "operator": "equal", "operand": true }, - { "key": "selection_empty", "operator": "equal", "operand": false, "match_all": true }, - { "key": "selector", "operator": "equal", "operand": "text.html.markdown", "match_all": true } - ] - }, - { "keys": ["super+ctrl+6"], "command": "insert_snippet", "args": {"contents": "###### $0"}, "context": - [ - { "key": "setting.auto_match_enabled", "operator": "equal", "operand": true }, - { "key": "selection_empty", "operator": "equal", "operand": true, "match_all": true }, - { "key": "following_text", "operator": "regex_contains", "operand": "^(?:\t| |\\)|]|\\}|$)", "match_all": true }, - { "key": "preceding_text", "operator": "not_regex_contains", "operand": "['a-zA-Z0-9_]$", "match_all": true }, - { "key": "eol_selector", "operator": "not_equal", "operand": "string.quoted.single", "match_all": true }, - { "key": "selector", "operator": "equal", "operand": "text.html.markdown", "match_all": true } - ] - }, - { "keys": ["super+ctrl+6"], "command": "insert_snippet", "args": {"contents": "######${0: ${SELECTION/(^( +)?(#+)?\\s*|\\s*(#+)?( +)?$)//g}}$1"}, "context": - [ - { "key": "setting.auto_match_enabled", "operator": "equal", "operand": true }, - { "key": "setting.mde.match_header_hashes", "operator": "equal", "operand": false }, - { "key": "selection_empty", "operator": "equal", "operand": false, "match_all": true }, - { "key": "selector", "operator": "equal", "operand": "text.html.markdown", "match_all": true } - ] - }, - { "keys": ["super+ctrl+6"], "command": "insert_snippet", "args": {"contents": "######${0: ${SELECTION/(^( +)?(#+)?\\s*|\\s*(#+)?( +)?$)//g} }######$1"}, "context": - [ - { "key": "setting.auto_match_enabled", "operator": "equal", "operand": true }, - { "key": "setting.mde.match_header_hashes", "operator": "equal", "operand": true }, - { "key": "selection_empty", "operator": "equal", "operand": false, "match_all": true }, - { "key": "selector", "operator": "equal", "operand": "text.html.markdown", "match_all": true } - ] - }, - { "keys": ["alt+shift+6"], "command": "reference_new_footnote", "context": - [ - { "key": "setting.mde.keymap_disable.reference_new_footnote", "operator": "not_equal", "operand": true }, - { "key": "selector", "operator": "equal", "operand": "text.html.markdown", "match_all": true } - ] - }, - { "keys": ["super+ctrl+s"], "command": "reference_organize", "context": - [ - { "key": "selector", "operator": "equal", "operand": "text.html.markdown", "match_all": true } - ] - }, - { "keys": ["super+shift+."], "command": "indent_quote", "context": - [ - { "key": "selector", "operator": "equal", "operand": "text.html.markdown", "match_all": true } - ] - }, - { "keys": ["super+shift+,"], "command": "deindent_quote", "context": - [ - { "key": "selector", "operator": "equal", "operand": "text.html.markdown", "match_all": true }, - { "key": "preceding_text", "operator": "regex_contains", "operand": "(> )+", "match_all": true } - ] - }, - { "keys": ["shift+tab"], "command": "fold_section", "context": - [ - { "key": "setting.mde.keymap_disable.fold_section", "operator": "not_equal", "operand": true }, - { "key": "selection_empty", "operator": "equal", "operand": true, "match_all": true }, - { "key": "preceding_text", "operator": "not_regex_match", "operand": "^\\s+", "match_all": true }, - { "key": "following_text", "operator": "not_regex_match", "operand": "^$", "match_all": true }, - { "key": "selector", "operator": "equal", "operand": "text.html.markdown", "match_all": true } - ] - }, - { "keys": ["shift+tab"], "command": "fold_section", "context": - [ - { "key": "setting.mde.keymap_disable.fold_section", "operator": "not_equal", "operand": true }, - { "key": "selection_empty", "operator": "equal", "operand": true, "match_all": true }, - { "key": "preceding_text", "operator": "not_regex_match", "operand": "^\\s+", "match_all": true }, - { "key": "selector", "operator": "not_equal", "operand": "markup.list", "match_all": true }, - { "key": "selector", "operator": "equal", "operand": "text.html.markdown", "match_all": true } - ] - }, - { "keys": ["shift+tab"], "command": "fold_section", "context": - [ - { "key": "setting.mde.keymap_disable.fold_section", "operator": "not_equal", "operand": true }, - { "key": "selection_empty", "operator": "equal", "operand": false, "match_all": true }, - { "key": "text", "operator": "regex_contains", "operand": "^(#{1,6}(?!#))|^(-{3,}|={3,})$"}, - { "key": "selector", "operator": "equal", "operand": "text.html.markdown", "match_all": true } - ] - }, - { "keys": ["ctrl+shift+tab"], "command": "show_fold_all_sections", "context": - [ - { "key": "setting.mde.keymap_disable.show_fold_all_sections", "operator": "not_equal", "operand": true }, - { "key": "selector", "operator": "equal", "operand": "text.html.markdown", "match_all": true } - ] - }, - { "keys": ["super+ctrl+pageup"], "command": "goto_previous_heading", "args": {"same_level": true}, "context": - [ - { "key": "setting.mde.keymap_disable.goto_previous_heading", "operator": "not_equal", "operand": true }, - { "key": "selector", "operator": "equal", "operand": "text.html.markdown", "match_all": true } - ] - }, - { "keys": ["super+ctrl+pagedown"], "command": "goto_next_heading", "args": {"same_level": true}, "context": - [ - { "key": "setting.mde.keymap_disable.goto_next_heading", "operator": "not_equal", "operand": true }, - { "key": "selector", "operator": "equal", "operand": "text.html.markdown", "match_all": true } - ] - }, - { "keys": ["super+shift+pageup"], "command": "goto_previous_heading", "args": {"same_level": false}, "context": - [ - { "key": "setting.mde.keymap_disable.goto_previous_heading", "operator": "not_equal", "operand": true }, - { "key": "selector", "operator": "equal", "operand": "text.html.markdown", "match_all": true } - ] - }, - { "keys": ["super+shift+pagedown"], "command": "goto_next_heading", "args": {"same_level": false}, "context": - [ - { "key": "setting.mde.keymap_disable.goto_next_heading", "operator": "not_equal", "operand": true }, - { "key": "selector", "operator": "equal", "operand": "text.html.markdown", "match_all": true } - ] - }, - {"keys": ["super+shift+h"], "command": "open_home_page", "context": - [ - { "key": "setting.mde.keymap_disable.open_home_page", "operator": "not_equal", "operand": true }, - { "key": "selector", "operator": "equal", "operand": "text.html.markdown", "match_all": true } - ] - }, - {"keys": ["super+shift+d"], "command": "open_page", "context": - [ - { "key": "setting.mde.keymap_disable.open_page", "operator": "not_equal", "operand": true }, - { "key": "selector", "operator": "equal", "operand": "meta.link.wiki.markdown", "match_all": true } - ] - }, - {"keys": ["super+shift+d"], "command": "make_page_reference", "context": - [ - { "key": "setting.mde.keymap_disable.make_page_reference", "operator": "not_equal", "operand": true }, - { "key": "selector", "operator": "equal", "operand": "text.html.markdown", "match_all": true }, - { "key": "selector", "operator": "not_equal", "operand": "meta.link.wiki.markdown", "match_all": true }, - { "key": "selector", "operator": "not_equal", "operand": "markup.underline.link.markdown", "match_all": true } - ] - }, - {"keys": ["super+shift+x"], "command": "list_back_links", "context": - [ - { "key": "setting.mde.keymap_disable.list_back_links", "operator": "not_equal", "operand": true }, - { "key": "selector", "operator": "equal", "operand": "text.html.markdown", "match_all": true } - ] - }, - {"keys": ["super+shift+j"], "command": "open_journal", "context": - [ - { "key": "setting.mde.keymap_disable.open_journal", "operator": "not_equal", "operand": true }, - { "key": "selector", "operator": "equal", "operand": "text.html.markdown", "match_all": true } - ] - } + { "keys": ["_"], "command": "insert_snippet", "args": {"contents": "_$0_"}, "context": + [ + { "key": "selector", "operator": "equal", "operand": "text.html.markdown - meta.frontmatter - meta.disable-markdown - markup.raw - markup.kbd", "match_all": true }, + { "key": "setting.auto_match_enabled", "operator": "equal", "operand": true }, + { "key": "selection_empty", "operator": "equal", "operand": true, "match_all": true }, + { "key": "eol_selector", "operator": "not_equal", "operand": "string.quoted.single", "match_all": true }, + { "key": "preceding_text", "operator": "not_regex_contains", "operand": "['a-zA-Z0-9_]$", "match_all": true }, + { "key": "following_text", "operator": "regex_contains", "operand": "^(?:\t| |\\)|]|\\}|$)", "match_all": true } + ] + }, + { "keys": ["_"], "command": "insert_snippet", "args": {"contents": "_${0:$SELECTION}_"}, "context": + [ + { "key": "selector", "operator": "equal", "operand": "text.html.markdown - meta.frontmatter - meta.disable-markdown - markup.raw - markup.kbd", "match_all": true }, + { "key": "setting.auto_match_enabled", "operator": "equal", "operand": true }, + { "key": "selection_empty", "operator": "equal", "operand": false, "match_all": true } + ] + }, + { "keys": ["_"], "command": "move", "args": {"by": "characters", "forward": true}, "context": + [ + { "key": "selector", "operator": "equal", "operand": "text.html.markdown - meta.frontmatter - meta.disable-markdown - markup.raw - markup.kbd", "match_all": true }, + { "key": "selection_empty", "operator": "equal", "operand": true, "match_all": true }, + { "key": "following_text", "operator": "regex_contains", "operand": "^_", "match_all": true } + ] + }, + { "keys": ["backspace"], "command": "run_macro_file", "args": {"file": "Packages/Default/Delete Left Right.sublime-macro"}, "context": + [ + { "key": "selector", "operator": "equal", "operand": "text.html.markdown - meta.frontmatter - meta.disable-markdown - markup.raw - markup.kbd", "match_all": true }, + { "key": "setting.auto_match_enabled", "operator": "equal", "operand": true }, + { "key": "selection_empty", "operator": "equal", "operand": true, "match_all": true }, + { "key": "preceding_text", "operator": "regex_contains", "operand": "_$", "match_all": true }, + { "key": "following_text", "operator": "regex_contains", "operand": "^_", "match_all": true } + ] + }, + { "keys": [" "], "command": "run_macro_file", "args": {"file": "Packages/MarkdownEditing/macros/Start List Item.sublime-macro"}, "context": + [ + { "key": "selector", "operator": "equal", "operand": "text.html.markdown - meta.frontmatter - meta.disable-markdown - markup.raw - markup.kbd", "match_all": true }, + { "key": "setting.auto_match_enabled", "operator": "equal", "operand": true }, + { "key": "selection_empty", "operator": "equal", "operand": true, "match_all": true }, + { "key": "preceding_text", "operator": "regex_contains", "operand": "\\_$", "match_all": true }, + { "key": "following_text", "operator": "regex_contains", "operand": "^\\_", "match_all": true } + ] + }, + { "keys": ["tab"], "command": "run_macro_file", "args": {"file": "Packages/MarkdownEditing/macros/Start List Item Tab.sublime-macro"}, "context": + [ + { "key": "selector", "operator": "equal", "operand": "text.html.markdown - meta.frontmatter - meta.disable-markdown - markup.raw - markup.kbd", "match_all": true }, + { "key": "setting.auto_match_enabled", "operator": "equal", "operand": true }, + { "key": "selection_empty", "operator": "equal", "operand": true, "match_all": true }, + { "key": "preceding_text", "operator": "regex_contains", "operand": "\\_$", "match_all": true }, + { "key": "following_text", "operator": "regex_contains", "operand": "^\\_", "match_all": true } + ] + }, + + // + // Auto-Pairing Inline Code + // + + { "keys": ["`"], "command": "insert_snippet", "args": {"contents": "`$0`"}, "context": + [ + { "key": "selector", "operator": "equal", "operand": "text.html.markdown - meta.frontmatter - meta.disable-markdown - markup.raw - markup.kbd", "match_all": true }, + { "key": "setting.auto_match_enabled", "operator": "equal", "operand": true }, + { "key": "selection_empty", "operator": "equal", "operand": true, "match_all": true }, + { "key": "preceding_text", "operator": "not_regex_contains", "operand": "[\\w`]$", "match_all": true }, + { "key": "following_text", "operator": "regex_contains", "operand": "^(?:\t| |\\)|]|\\}|\\.|,|$)", "match_all": true } + ] + }, + { "keys": ["`"], "command": "insert_snippet", "args": {"contents": "`${0:$SELECTION}`"}, "context": + [ + { "key": "selector", "operator": "equal", "operand": "text.html.markdown - meta.frontmatter - meta.disable-markdown - markup.raw - markup.kbd", "match_all": true }, + { "key": "setting.auto_match_enabled", "operator": "equal", "operand": true }, + { "key": "selection_empty", "operator": "equal", "operand": false, "match_all": true } + ] + }, + { "keys": ["`"], "command": "move", "args": {"by": "characters", "forward": true}, "context": + [ + { "key": "selector", "operator": "equal", "operand": "text.html.markdown - meta.frontmatter - meta.disable-markdown - markup.raw - markup.kbd", "match_all": true }, + { "key": "selection_empty", "operator": "equal", "operand": true, "match_all": true }, + { "key": "following_text", "operator": "regex_contains", "operand": "^`", "match_all": true } + ] + }, + { "keys": ["backspace"], "command": "run_macro_file", "args": {"file": "Packages/Default/Delete Left Right.sublime-macro"}, "context": + [ + { "key": "selector", "operator": "equal", "operand": "text.html.markdown - meta.frontmatter - meta.disable-markdown - markup.raw - markup.kbd", "match_all": true }, + { "key": "setting.auto_match_enabled", "operator": "equal", "operand": true }, + { "key": "selection_empty", "operator": "equal", "operand": true, "match_all": true }, + { "key": "preceding_text", "operator": "regex_contains", "operand": "`$", "match_all": true }, + { "key": "following_text", "operator": "regex_contains", "operand": "^`", "match_all": true } + ] + }, + + // + // Auto-Pairing Strike Through + // + + { "keys": ["~"], "command": "insert_snippet", "args": {"contents": "~~${0:$SELECTION}~~"}, "context": + [ + { "key": "selector", "operator": "equal", "operand": "text.html.markdown - meta.frontmatter - meta.disable-markdown - markup.raw - markup.kbd", "match_all": true }, + { "key": "setting.auto_match_enabled", "operator": "equal", "operand": true }, + { "key": "selection_empty", "operator": "equal", "operand": false, "match_all": true } + ] + }, + { "keys": ["backspace"], "command": "run_macro_file", "args": {"file": "Packages/MarkdownEditing/macros/Delete Left Right 2.sublime-macro"}, "context": + [ + { "key": "selector", "operator": "equal", "operand": "text.html.markdown - meta.frontmatter - meta.disable-markdown - markup.raw - markup.kbd", "match_all": true }, + { "key": "setting.auto_match_enabled", "operator": "equal", "operand": true }, + { "key": "selection_empty", "operator": "equal", "operand": true, "match_all": true }, + { "key": "preceding_text", "operator": "regex_contains", "operand": "~~$", "match_all": true }, + { "key": "following_text", "operator": "regex_contains", "operand": "^~~", "match_all": true } + ] + }, + + // + // Text Formatting Bold + // + + // auto-pair if not within a word + { "keys": ["super+alt+b"], "command": "insert_snippet", "args": {"contents": "**$0**"}, "context": + [ + { "key": "selector", "operator": "equal", "operand": "text.html.markdown - meta.frontmatter - meta.disable-markdown - markup.raw - markup.kbd - markup.bold - markup.bold_italic", "match_all": true }, + { "key": "setting.mde.bold_marker_asterisk", "operator": "equal", "operand": true }, + { "key": "selection_empty", "operator": "equal", "operand": true, "match_all": true }, + { "key": "eol_selector", "operator": "not_equal", "operand": "string.quoted.single", "match_all": true }, + { "key": "preceding_text", "operator": "not_regex_contains", "operand": "['a-zA-Z0-9_*]$", "match_all": true }, + { "key": "following_text", "operator": "regex_contains", "operand": "^(?:\t| |\\)|]|\\}|$)", "match_all": true } + ] + }, + { "keys": ["super+alt+b"], "command": "insert_snippet", "args": {"contents": "__$0__"}, "context": + [ + { "key": "selector", "operator": "equal", "operand": "text.html.markdown - meta.frontmatter - meta.disable-markdown - markup.raw - markup.kbd - markup.bold - markup.bold_italic", "match_all": true }, + { "key": "setting.mde.bold_marker_asterisk", "operator": "equal", "operand": false }, + { "key": "selection_empty", "operator": "equal", "operand": true, "match_all": true }, + { "key": "eol_selector", "operator": "not_equal", "operand": "string.quoted.single", "match_all": true }, + { "key": "preceding_text", "operator": "not_regex_contains", "operand": "['a-zA-Z0-9_*]$", "match_all": true }, + { "key": "following_text", "operator": "regex_contains", "operand": "^(?:\t| |\\)|]|\\}|$)", "match_all": true } + ] + }, + // Transform a word to bold if caret is at the beginning, in the middle of or at the end of a word + { "keys": ["super+alt+b"], "command": "run_macro_file", "args": {"file": "Packages/MarkdownEditing/macros/Transform Word - Bold (Asterisk).sublime-macro"}, "context": + [ + { "key": "selector", "operator": "equal", "operand": "text.html.markdown - meta.frontmatter - meta.disable-markdown - markup.raw - markup.kbd - markup.bold - markup.bold_italic", "match_all": true }, + { "key": "setting.mde.bold_marker_asterisk", "operator": "equal", "operand": true }, + { "key": "selection_empty", "operator": "equal", "operand": true, "match_all": true }, + { "key": "preceding_text", "operator": "regex_contains", "operand": "\\w$", "match_all": true } + ] + }, + { "keys": ["super+alt+b"], "command": "run_macro_file", "args": {"file": "Packages/MarkdownEditing/macros/Transform Word - Bold (Asterisk).sublime-macro"}, "context": + [ + { "key": "selector", "operator": "equal", "operand": "text.html.markdown - meta.frontmatter - meta.disable-markdown - markup.raw - markup.kbd - markup.bold - markup.bold_italic", "match_all": true }, + { "key": "setting.mde.bold_marker_asterisk", "operator": "equal", "operand": true }, + { "key": "selection_empty", "operator": "equal", "operand": true, "match_all": true }, + { "key": "following_text", "operator": "regex_contains", "operand": "^\\w", "match_all": true } + ] + }, + { "keys": ["super+alt+b"], "command": "run_macro_file", "args": {"file": "Packages/MarkdownEditing/macros/Transform Word - Bold (Underscore).sublime-macro"}, "context": + [ + { "key": "selector", "operator": "equal", "operand": "text.html.markdown - meta.frontmatter - meta.disable-markdown - markup.raw - markup.kbd - markup.bold - markup.bold_italic", "match_all": true }, + { "key": "setting.mde.bold_marker_asterisk", "operator": "equal", "operand": false }, + { "key": "selection_empty", "operator": "equal", "operand": true, "match_all": true }, + { "key": "preceding_text", "operator": "regex_contains", "operand": "\\w$", "match_all": true } + ] + }, + { "keys": ["super+alt+b"], "command": "run_macro_file", "args": {"file": "Packages/MarkdownEditing/macros/Transform Word - Bold (Underscore).sublime-macro"}, "context": + [ + { "key": "selector", "operator": "equal", "operand": "text.html.markdown - meta.frontmatter - meta.disable-markdown - markup.raw - markup.kbd - markup.bold - markup.bold_italic", "match_all": true }, + { "key": "setting.mde.bold_marker_asterisk", "operator": "equal", "operand": false }, + { "key": "selection_empty", "operator": "equal", "operand": true, "match_all": true }, + { "key": "following_text", "operator": "regex_contains", "operand": "^\\w", "match_all": true } + ] + }, + // Transform selection to bold + { "keys": ["super+alt+b"], "command": "insert_snippet", "args": {"contents": "**${SELECTION/^\\*\\*|^__|\\*\\*$|__$//g}**"}, "context": + [ + { "key": "selector", "operator": "equal", "operand": "text.html.markdown - meta.frontmatter - meta.disable-markdown - markup.raw - markup.kbd - markup.bold - markup.bold_italic", "match_all": true }, + { "key": "setting.mde.bold_marker_asterisk", "operator": "equal", "operand": true }, + { "key": "selection_empty", "operator": "equal", "operand": false, "match_all": true }, + { "key": "preceding_text", "operator": "not_regex_contains", "operand": "\\*$|__$", "match_all": true }, + { "key": "following_text", "operator": "not_regex_contains", "operand": "^\\*|^__", "match_all": true } + ] + }, + { "keys": ["super+alt+b"], "command": "insert_snippet", "args": {"contents": "__${SELECTION/^\\*\\*|^__|\\*\\*$|__$//g}__"}, "context": + [ + { "key": "selector", "operator": "equal", "operand": "text.html.markdown - meta.frontmatter - meta.disable-markdown - markup.raw - markup.kbd - markup.bold - markup.bold_italic", "match_all": true }, + { "key": "setting.mde.bold_marker_asterisk", "operator": "equal", "operand": false }, + { "key": "selection_empty", "operator": "equal", "operand": false, "match_all": true }, + { "key": "preceding_text", "operator": "not_regex_contains", "operand": "\\*$|__$", "match_all": true }, + { "key": "following_text", "operator": "not_regex_contains", "operand": "^\\*|^__", "match_all": true } + ] + }, + // Unbold bold text + { "keys": ["super+alt+b"], "command": "run_macro_file", "args": {"file": "Packages/MarkdownEditing/macros/Transform Word - Unbold.sublime-macro"}, "context": + [ + { "key": "selector", "operator": "equal", "operand": "text.html.markdown markup.bold - punctuation, text.html.markdown markup.bold_italic - punctuation", "match_all": true } + ] + }, + + // + // Text Formatting Italic + // + + // auto-pair if not within a word + { "keys": ["super+alt+i"], "command": "insert_snippet", "args": {"contents": "*$0*"}, "context": + [ + { "key": "selector", "operator": "equal", "operand": "text.html.markdown - meta.frontmatter - meta.disable-markdown - markup.raw - markup.kbd - markup.italic - markup.bold_italic", "match_all": true }, + { "key": "setting.mde.italic_marker_asterisk", "operator": "equal", "operand": true }, + { "key": "selection_empty", "operator": "equal", "operand": true, "match_all": true }, + { "key": "eol_selector", "operator": "not_equal", "operand": "string.quoted.single", "match_all": true }, + { "key": "preceding_text", "operator": "not_regex_contains", "operand": "['a-zA-Z0-9_*]$", "match_all": true }, + { "key": "following_text", "operator": "regex_contains", "operand": "^(?:\t| |\\)|]|\\}|$)", "match_all": true } + ] + }, + { "keys": ["super+alt+i"], "command": "insert_snippet", "args": {"contents": "_$0_"}, "context": + [ + { "key": "selector", "operator": "equal", "operand": "text.html.markdown - meta.frontmatter - meta.disable-markdown - markup.raw - markup.kbd - markup.italic - markup.bold_italic", "match_all": true }, + { "key": "setting.mde.italic_marker_asterisk", "operator": "equal", "operand": false }, + { "key": "selection_empty", "operator": "equal", "operand": true, "match_all": true }, + { "key": "eol_selector", "operator": "not_equal", "operand": "string.quoted.single", "match_all": true }, + { "key": "preceding_text", "operator": "not_regex_contains", "operand": "['a-zA-Z0-9_*]$", "match_all": true }, + { "key": "following_text", "operator": "regex_contains", "operand": "^(?:\t| |\\)|]|\\}|$)", "match_all": true } + ] + }, + // Transform a word to bold if caret is at the beginning, in the middle of or at the end of a word + { "keys": ["super+alt+i"], "command": "run_macro_file", "args": {"file": "Packages/MarkdownEditing/macros/Transform Word - Italic (Asterisk).sublime-macro"}, "context": + [ + { "key": "selector", "operator": "equal", "operand": "text.html.markdown - meta.frontmatter - meta.disable-markdown - markup.raw - markup.kbd - markup.italic - markup.bold_italic", "match_all": true }, + { "key": "setting.mde.italic_marker_asterisk", "operator": "equal", "operand": true }, + { "key": "selection_empty", "operator": "equal", "operand": true, "match_all": true }, + { "key": "preceding_text", "operator": "regex_contains", "operand": "\\w$", "match_all": true } + ] + }, + { "keys": ["super+alt+i"], "command": "run_macro_file", "args": {"file": "Packages/MarkdownEditing/macros/Transform Word - Italic (Asterisk).sublime-macro"}, "context": + [ + { "key": "selector", "operator": "equal", "operand": "text.html.markdown - meta.frontmatter - meta.disable-markdown - markup.raw - markup.kbd - markup.italic - markup.bold_italic", "match_all": true }, + { "key": "setting.mde.italic_marker_asterisk", "operator": "equal", "operand": true }, + { "key": "selection_empty", "operator": "equal", "operand": true, "match_all": true }, + { "key": "following_text", "operator": "regex_contains", "operand": "^\\w", "match_all": true } + ] + }, + { "keys": ["super+alt+i"], "command": "run_macro_file", "args": {"file": "Packages/MarkdownEditing/macros/Transform Word - Italic (Underscore).sublime-macro"}, "context": + [ + { "key": "selector", "operator": "equal", "operand": "text.html.markdown - meta.frontmatter - meta.disable-markdown - markup.raw - markup.kbd - markup.italic - markup.bold_italic", "match_all": true }, + { "key": "setting.mde.italic_marker_asterisk", "operator": "equal", "operand": false }, + { "key": "selection_empty", "operator": "equal", "operand": true, "match_all": true }, + { "key": "preceding_text", "operator": "regex_contains", "operand": "\\w$", "match_all": true } + ] + }, + { "keys": ["super+alt+i"], "command": "run_macro_file", "args": {"file": "Packages/MarkdownEditing/macros/Transform Word - Italic (Underscore).sublime-macro"}, "context": + [ + { "key": "selector", "operator": "equal", "operand": "text.html.markdown - meta.frontmatter - meta.disable-markdown - markup.raw - markup.kbd - markup.italic - markup.bold_italic", "match_all": true }, + { "key": "setting.mde.italic_marker_asterisk", "operator": "equal", "operand": false }, + { "key": "selection_empty", "operator": "equal", "operand": true, "match_all": true }, + { "key": "following_text", "operator": "regex_contains", "operand": "^\\w", "match_all": true } + ] + }, + // Transform selection to italics + { "keys": ["super+alt+i"], "command": "insert_snippet", "args": {"contents": "*${SELECTION/(^[\\*_]*|[\\*_]*$)//g}*"}, "context": + [ + { "key": "selector", "operator": "equal", "operand": "text.html.markdown - meta.frontmatter - meta.disable-markdown - markup.raw - markup.kbd - markup.italic - markup.bold_italic", "match_all": true }, + { "key": "setting.mde.italic_marker_asterisk", "operator": "equal", "operand": true }, + { "key": "selection_empty", "operator": "equal", "operand": false, "match_all": true }, + { "key": "preceding_text", "operator": "not_regex_contains", "operand": "\\*$|_$", "match_all": true }, + { "key": "following_text", "operator": "not_regex_contains", "operand": "^\\*|^_", "match_all": true } + ] + }, + // Remove italics style from text + { "keys": ["super+alt+i"], "command": "insert_snippet", "args": {"contents": "_${SELECTION/(^[\\*_]*|[\\*_]*$)//g}_"}, "context": + [ + { "key": "selector", "operator": "equal", "operand": "text.html.markdown - meta.frontmatter - meta.disable-markdown - markup.raw - markup.kbd - markup.italic - markup.bold_italic", "match_all": true }, + { "key": "setting.mde.italic_marker_asterisk", "operator": "equal", "operand": false }, + { "key": "selection_empty", "operator": "equal", "operand": false, "match_all": true }, + { "key": "preceding_text", "operator": "not_regex_contains", "operand": "\\*$|_$", "match_all": true }, + { "key": "following_text", "operator": "not_regex_contains", "operand": "^\\*|^_", "match_all": true } + ] + }, + { "keys": ["super+alt+i"], "command": "run_macro_file", "args": {"file": "Packages/MarkdownEditing/macros/Transform Word - Unitalicize.sublime-macro"}, "context": + [ + { "key": "selector", "operator": "equal", "operand": "text.html.markdown markup.italic - punctuation, text.html.markdown markup.bold_italic - punctuation", "match_all": true } + ] + }, + + // + // Headings + // + + { "keys": ["super+ctrl+keypad0"], "command": "mde_change_headings_level", "args": {"to": 0}, "context": + [ + { "key": "selector", "operator": "equal", "operand": "text.html.markdown - meta.frontmatter - meta.disable-markdown - markup.raw", "match_all": true } + ] + }, + { "keys": ["super+ctrl+0"], "command": "mde_change_headings_level", "args": {"to": 0}, "context": + [ + { "key": "selector", "operator": "equal", "operand": "text.html.markdown - meta.frontmatter - meta.disable-markdown - markup.raw", "match_all": true } + ] + }, + { "keys": ["super+ctrl+keypad1"], "command": "mde_change_headings_level", "args": {"to": 1}, "context": + [ + { "key": "selector", "operator": "equal", "operand": "text.html.markdown - meta.frontmatter - meta.disable-markdown - markup.raw", "match_all": true } + ] + }, + { "keys": ["super+ctrl+1"], "command": "mde_change_headings_level", "args": {"to": 1}, "context": + [ + { "key": "selector", "operator": "equal", "operand": "text.html.markdown - meta.frontmatter - meta.disable-markdown - markup.raw", "match_all": true } + ] + }, + { "keys": ["super+ctrl+keypad2"], "command": "mde_change_headings_level", "args": {"to": 2}, "context": + [ + { "key": "selector", "operator": "equal", "operand": "text.html.markdown - meta.frontmatter - meta.disable-markdown - markup.raw", "match_all": true } + ] + }, + { "keys": ["super+ctrl+2"], "command": "mde_change_headings_level", "args": {"to": 2}, "context": + [ + { "key": "selector", "operator": "equal", "operand": "text.html.markdown - meta.frontmatter - meta.disable-markdown - markup.raw", "match_all": true } + ] + }, + { "keys": ["super+ctrl+keypad3"], "command": "mde_change_headings_level", "args": {"to": 3}, "context": + [ + { "key": "selector", "operator": "equal", "operand": "text.html.markdown - meta.frontmatter - meta.disable-markdown - markup.raw", "match_all": true } + ] + }, + { "keys": ["super+ctrl+3"], "command": "mde_change_headings_level", "args": {"to": 3}, "context": + [ + { "key": "selector", "operator": "equal", "operand": "text.html.markdown - meta.frontmatter - meta.disable-markdown - markup.raw", "match_all": true } + ] + }, + { "keys": ["super+ctrl+keypad4"], "command": "mde_change_headings_level", "args": {"to": 4}, "context": + [ + { "key": "selector", "operator": "equal", "operand": "text.html.markdown - meta.frontmatter - meta.disable-markdown - markup.raw", "match_all": true } + ] + }, + { "keys": ["super+ctrl+4"], "command": "mde_change_headings_level", "args": {"to": 4}, "context": + [ + { "key": "selector", "operator": "equal", "operand": "text.html.markdown - meta.frontmatter - meta.disable-markdown - markup.raw", "match_all": true } + ] + }, + { "keys": ["super+ctrl+keypad5"], "command": "mde_change_headings_level", "args": {"to": 5}, "context": + [ + { "key": "selector", "operator": "equal", "operand": "text.html.markdown - meta.frontmatter - meta.disable-markdown - markup.raw", "match_all": true } + ] + }, + { "keys": ["super+ctrl+5"], "command": "mde_change_headings_level", "args": {"to": 5}, "context": + [ + { "key": "selector", "operator": "equal", "operand": "text.html.markdown - meta.frontmatter - meta.disable-markdown - markup.raw", "match_all": true } + ] + }, + { "keys": ["super+ctrl+keypad6"], "command": "mde_change_headings_level", "args": {"to": 6}, "context": + [ + { "key": "selector", "operator": "equal", "operand": "text.html.markdown - meta.frontmatter - meta.disable-markdown - markup.raw", "match_all": true } + ] + }, + { "keys": ["super+ctrl+6"], "command": "mde_change_headings_level", "args": {"to": 6}, "context": + [ + { "key": "selector", "operator": "equal", "operand": "text.html.markdown - meta.frontmatter - meta.disable-markdown - markup.raw", "match_all": true } + ] + }, + { "keys": ["ctrl+alt+."], "command": "mde_change_headings_level", "args": {"by": 1}, "context": + [ + { "key": "selector", "operator": "equal", "operand": "text.html.markdown - meta.frontmatter - meta.disable-markdown - markup.raw", "match_all": true } + ] + }, + { "keys": ["ctrl+alt+,"], "command": "mde_change_headings_level", "args": {"by": -1}, "context": + [ + { "key": "selector", "operator": "equal", "operand": "text.html.markdown - meta.frontmatter - meta.disable-markdown - markup.raw", "match_all": true } + ] + }, + // If nothing is selected, pressing hash in front of heading label increases level by one + { "keys": ["#"], "command": "mde_change_headings_level", "args": {"by": 1}, "context": + [ + { "key": "selector", "operator": "equal", "operand": "text.html.markdown - meta.frontmatter - meta.disable-markdown - markup.raw - markup.kbd", "match_all": true }, + { "key": "setting.mde.auto_match_heading_hashes", "operator": "equal", "operand": true }, + { "key": "selection_empty", "operator": "equal", "operand": true, "match_all": true }, + { "key": "preceding_text", "operator": "regex_match", "operand": "^[\\s>]*#*\\s*$", "match_all": true } + ] + }, + // If nothing is selected, pressing backspace within or directly after leading hashes decreases heading level + { "keys": ["backspace"], "command": "mde_change_headings_level", "args": {"by": -1}, "context": + [ + { "key": "selector", "operator": "equal", "operand": "text.html.markdown - meta.frontmatter - meta.disable-markdown - markup.raw - markup.kbd", "match_all": true }, + { "key": "setting.mde.auto_match_heading_hashes", "operator": "equal", "operand": true }, + { "key": "selection_empty", "operator": "equal", "operand": true, "match_all": true }, + { "key": "preceding_text", "operator": "regex_match", "operand": "^[\\s>]*#+\\s?$", "match_all": true } + ] + }, + // If nothing is selected, pressing delete within or directly in front of leading hashes decreases heading level + { "keys": ["delete"], "command": "mde_change_headings_level", "args": {"by": -1}, "context": + [ + { "key": "selector", "operator": "equal", "operand": "text.html.markdown - meta.frontmatter - meta.disable-markdown - markup.raw - markup.kbd", "match_all": true }, + { "key": "setting.mde.auto_match_heading_hashes", "operator": "equal", "operand": true }, + { "key": "selection_empty", "operator": "equal", "operand": true, "match_all": true }, + { "key": "preceding_text", "operator": "regex_match", "operand": "^[\\s>]*#*\\s*$", "match_all": true }, + { "key": "following_text", "operator": "regex_contains", "operand": "^#", "match_all": true } + ] + }, + { "keys": ["enter"], "command": "run_macro_file", "args": {"file": "Packages/MarkdownEditing/macros/Balance Trailing Hashes.sublime-macro"}, "context": + [ + { "key": "selector", "operator": "equal", "operand": "text.html.markdown - meta.frontmatter - meta.disable-markdown - markup.raw - markup.kbd", "match_all": true }, + { "key": "setting.mde.auto_match_heading_hashes", "operator": "equal", "operand": true }, + { "key": "setting.mde.match_heading_hashes", "operator": "equal", "operand": true }, + { "key": "preceding_text", "operator": "regex_contains", "operand": "^[\\s>]*#+\\s+", "match_all": true }, + { "key": "following_text", "operator": "regex_contains", "operand": "^\\s*$", "match_all": true }, + { "key": "auto_complete_visible", "operator": "equal", "operand": false } + ] + }, + { "keys": ["enter"], "command": "run_macro_file", "args": {"file": "Packages/MarkdownEditing/macros/Balance Trailing Hashes.sublime-macro"}, "context": + [ + { "key": "selector", "operator": "equal", "operand": "text.html.markdown - meta.frontmatter - meta.disable-markdown - markup.raw - markup.kbd", "match_all": true }, + { "key": "setting.mde.auto_match_heading_hashes", "operator": "equal", "operand": true }, + { "key": "setting.mde.match_heading_hashes", "operator": "equal", "operand": true }, + { "key": "preceding_text", "operator": "regex_contains", "operand": "^[\\s>]*#+\\s+", "match_all": true }, + { "key": "following_text", "operator": "regex_contains", "operand": "^\\s*$", "match_all": true }, + { "key": "setting.auto_complete_commit_on_tab" } + ] + }, + { "keys": ["enter"], "command": "run_macro_file", "args": {"file": "Packages/MarkdownEditing/macros/Remove Trailing Hashes.sublime-macro"}, "context": + [ + { "key": "selector", "operator": "equal", "operand": "text.html.markdown - meta.frontmatter - meta.disable-markdown - markup.raw - markup.kbd", "match_all": true }, + { "key": "setting.mde.auto_match_heading_hashes", "operator": "equal", "operand": true }, + { "key": "setting.mde.match_heading_hashes", "operator": "equal", "operand": false }, + { "key": "preceding_text", "operator": "regex_contains", "operand": "^[\\s>]*#+\\s+", "match_all": true }, + { "key": "following_text", "operator": "regex_contains", "operand": "^\\s*$", "match_all": true }, + { "key": "auto_complete_visible", "operator": "equal", "operand": false } + ] + }, + { "keys": ["enter"], "command": "run_macro_file", "args": {"file": "Packages/MarkdownEditing/macros/Remove Trailing Hashes.sublime-macro"}, "context": + [ + { "key": "selector", "operator": "equal", "operand": "text.html.markdown - meta.frontmatter - meta.disable-markdown - markup.raw - markup.kbd", "match_all": true }, + { "key": "setting.mde.auto_match_heading_hashes", "operator": "equal", "operand": true }, + { "key": "setting.mde.match_heading_hashes", "operator": "equal", "operand": false }, + { "key": "preceding_text", "operator": "regex_contains", "operand": "^[\\s>]*#+\\s+", "match_all": true }, + { "key": "following_text", "operator": "regex_contains", "operand": "^\\s*$", "match_all": true }, + { "key": "setting.auto_complete_commit_on_tab" } + ] + }, + { "keys": ["tab"], "command": "mde_complete_underlined_headings", "context": + [ + { "key": "selector", "operator": "equal", "operand": "text.html.markdown - meta.frontmatter - meta.disable-markdown - markup.raw - markup.kbd", "match_all": true }, + { "key": "selection_empty", "operator": "equal", "operand": true, "match_all": true }, + { "key": "preceding_text", "operator": "regex_contains", "operand": "^\\-+$|^\\=+$", "match_all": true }, + { "key": "auto_complete_visible", "operator": "equal", "operand": false, "match_all": true } + ] + }, + { "keys": ["super+ctrl+pageup"], "command": "mde_goto_previous_heading", "args": {"same_level": true}, "context": + [ + { "key": "selector", "operator": "equal", "operand": "text.html.markdown", "match_all": true }, + { "key": "setting.mde.keymap_disable.goto_previous_heading", "operator": "not_equal", "operand": true } + ] + }, + { "keys": ["super+ctrl+pagedown"], "command": "mde_goto_next_heading", "args": {"same_level": true}, "context": + [ + { "key": "selector", "operator": "equal", "operand": "text.html.markdown", "match_all": true }, + { "key": "setting.mde.keymap_disable.goto_next_heading", "operator": "not_equal", "operand": true } + ] + }, + { "keys": ["super+shift+pageup"], "command": "mde_goto_previous_heading", "args": {"same_level": false}, "context": + [ + { "key": "selector", "operator": "equal", "operand": "text.html.markdown", "match_all": true }, + { "key": "setting.mde.keymap_disable.goto_previous_heading", "operator": "not_equal", "operand": true } + ] + }, + { "keys": ["super+shift+pagedown"], "command": "mde_goto_next_heading", "args": {"same_level": false}, "context": + [ + { "key": "selector", "operator": "equal", "operand": "text.html.markdown", "match_all": true }, + { "key": "setting.mde.keymap_disable.goto_next_heading", "operator": "not_equal", "operand": true } + ] + }, + + // + // Folding + // + + { "keys": ["super+k", "super+keypad0"], "command": "mde_unfold_all_sections", "context": + [ + { "key": "selector", "operator": "equal", "operand": "text.html.markdown - meta.frontmatter - meta.disable-markdown - markup.raw", "match_all": true } + ] + }, + { "keys": ["super+k", "super+0"], "command": "mde_unfold_all_sections", "context": + [ + { "key": "selector", "operator": "equal", "operand": "text.html.markdown - meta.frontmatter - meta.disable-markdown - markup.raw", "match_all": true } + ] + }, + { "keys": ["super+k", "super+keypad1"], "command": "mde_fold_all_sections", "args": {"target_level": 1}, "context": + [ + { "key": "selector", "operator": "equal", "operand": "text.html.markdown - meta.frontmatter - meta.disable-markdown - markup.raw", "match_all": true } + ] + }, + { "keys": ["super+k", "super+1"], "command": "mde_fold_all_sections", "args": {"target_level": 1}, "context": + [ + { "key": "selector", "operator": "equal", "operand": "text.html.markdown - meta.frontmatter - meta.disable-markdown - markup.raw", "match_all": true } + ] + }, + { "keys": ["super+k", "super+keypad2"], "command": "mde_fold_all_sections", "args": {"target_level": 2}, "context": + [ + { "key": "selector", "operator": "equal", "operand": "text.html.markdown - meta.frontmatter - meta.disable-markdown - markup.raw", "match_all": true } + ] + }, + { "keys": ["super+k", "super+2"], "command": "mde_fold_all_sections", "args": {"target_level": 2}, "context": + [ + { "key": "selector", "operator": "equal", "operand": "text.html.markdown - meta.frontmatter - meta.disable-markdown - markup.raw", "match_all": true } + ] + }, + { "keys": ["super+k", "super+keypad3"], "command": "mde_fold_all_sections", "args": {"target_level": 3}, "context": + [ + { "key": "selector", "operator": "equal", "operand": "text.html.markdown - meta.frontmatter - meta.disable-markdown - markup.raw", "match_all": true } + ] + }, + { "keys": ["super+k", "super+3"], "command": "mde_fold_all_sections", "args": {"target_level": 3}, "context": + [ + { "key": "selector", "operator": "equal", "operand": "text.html.markdown - meta.frontmatter - meta.disable-markdown - markup.raw", "match_all": true } + ] + }, + { "keys": ["super+k", "super+keypad4"], "command": "mde_fold_all_sections", "args": {"target_level": 4}, "context": + [ + { "key": "selector", "operator": "equal", "operand": "text.html.markdown - meta.frontmatter - meta.disable-markdown - markup.raw", "match_all": true } + ] + }, + { "keys": ["super+k", "super+4"], "command": "mde_fold_all_sections", "args": {"target_level": 4}, "context": + [ + { "key": "selector", "operator": "equal", "operand": "text.html.markdown - meta.frontmatter - meta.disable-markdown - markup.raw", "match_all": true } + ] + }, + { "keys": ["super+k", "super+keypad5"], "command": "mde_fold_all_sections", "args": {"target_level": 5}, "context": + [ + { "key": "selector", "operator": "equal", "operand": "text.html.markdown - meta.frontmatter - meta.disable-markdown - markup.raw", "match_all": true } + ] + }, + { "keys": ["super+k", "super+5"], "command": "mde_fold_all_sections", "args": {"target_level": 5}, "context": + [ + { "key": "selector", "operator": "equal", "operand": "text.html.markdown - meta.frontmatter - meta.disable-markdown - markup.raw", "match_all": true } + ] + }, + { "keys": ["super+k", "super+keypad6"], "command": "mde_fold_all_sections", "args": {"target_level": 6}, "context": + [ + { "key": "selector", "operator": "equal", "operand": "text.html.markdown - meta.frontmatter - meta.disable-markdown - markup.raw", "match_all": true } + ] + }, + { "keys": ["super+k", "super+6"], "command": "mde_fold_all_sections", "args": {"target_level": 6}, "context": + [ + { "key": "selector", "operator": "equal", "operand": "text.html.markdown - meta.frontmatter - meta.disable-markdown - markup.raw", "match_all": true } + ] + }, + { "keys": ["super+k", "super+keypad9"], "command": "mde_fold_all_sections", "args": {"target_level": 0}, "context": + [ + { "key": "selector", "operator": "equal", "operand": "text.html.markdown - meta.frontmatter - meta.disable-markdown - markup.raw", "match_all": true } + ] + }, + { "keys": ["super+k", "super+9"], "command": "mde_fold_all_sections", "args": {"target_level": 0}, "context": + [ + { "key": "selector", "operator": "equal", "operand": "text.html.markdown - meta.frontmatter - meta.disable-markdown - markup.raw", "match_all": true } + ] + }, + { "keys": ["shift+tab"], "command": "mde_fold_section", "context": + [ + { "key": "selector", "operator": "equal", "operand": "text.html.markdown - meta.frontmatter - meta.disable-markdown - markup.raw - markup.list", "match_all": true }, + { "key": "setting.mde.keymap_disable.fold_section", "operator": "not_equal", "operand": true }, + { "key": "selection_empty", "operator": "equal", "operand": true, "match_all": true }, + { "key": "has_prev_field", "operator": "equal", "operand": false }, + { "key": "overlay_visible", "operator": "equal", "operand": false }, + { "key": "preceding_text", "operator": "not_regex_match", "operand": "^\\s+", "match_all": true } + ] + }, + { "keys": ["shift+tab"], "command": "mde_fold_section", "context": + [ + { "key": "selector", "operator": "equal", "operand": "text.html.markdown", "match_all": true }, + { "key": "setting.mde.keymap_disable.fold_section", "operator": "not_equal", "operand": true }, + { "key": "selection_empty", "operator": "equal", "operand": false, "match_all": true }, + { "key": "has_prev_field", "operator": "equal", "operand": false }, + { "key": "overlay_visible", "operator": "equal", "operand": false }, + { "key": "text", "operator": "regex_contains", "operand": "^(#{1,6}(?!#))|^(-{3,}|={3,})$"} + ] + }, + { "keys": ["ctrl+shift+tab"], "command": "mde_show_fold_all_sections", "context": + [ + { "key": "selector", "operator": "equal", "operand": "text.html.markdown", "match_all": true }, + { "key": "setting.mde.keymap_disable.show_fold_all_sections", "operator": "not_equal", "operand": true } + ] + }, + + // + // Lists + // + + // Create new GFM Task + { "keys": ["super+alt+t"], "command": "insert_snippet", "args": {"contents": "* [ ] $0"}, "context": + [ + { "key": "selector", "operator": "equal", "operand": "text.html.markdown - meta.frontmatter - meta.disable-markdown - markup.raw - markup.kbd - meta.table", "match_all": true }, + { "key": "setting.auto_match_enabled", "operator": "equal", "operand": true }, + { "key": "setting.mde.list_align_text", "operator": "equal", "operand": false }, + { "key": "selection_empty", "operator": "equal", "operand": true, "match_all": true }, + { "key": "preceding_text", "operator": "regex_match", "operand": "^[\\s>]*$", "match_all": true }, + { "key": "following_text", "operator": "regex_match", "operand": "^\\s*$", "match_all": true } + ] + }, + { "keys": ["super+alt+t"], "command": "insert_snippet", "args": {"contents": "* [ ]\t$0"}, "context": + [ + { "key": "selector", "operator": "equal", "operand": "text.html.markdown - meta.frontmatter - meta.disable-markdown - markup.raw - markup.kbd - meta.table", "match_all": true }, + { "key": "setting.auto_match_enabled", "operator": "equal", "operand": true }, + { "key": "setting.mde.list_align_text", "operator": "equal", "operand": true }, + { "key": "selection_empty", "operator": "equal", "operand": true, "match_all": true }, + { "key": "preceding_text", "operator": "regex_match", "operand": "^[\\s>]*$", "match_all": true }, + { "key": "following_text", "operator": "regex_match", "operand": "^\\s*$", "match_all": true } + ] + }, + // Convert List Item to GFM Task + { "keys": ["super+alt+t"], "command": "run_macro_file", "args": {"file": "Packages/MarkdownEditing/macros/Convert List to Task.sublime-macro"}, "context": + [ + { "key": "selector", "operator": "equal", "operand": "text.html.markdown - meta.frontmatter - meta.disable-markdown - markup.raw - markup.kbd - meta.table", "match_all": true }, + { "key": "setting.auto_match_enabled", "operator": "equal", "operand": true }, + { "key": "setting.mde.list_align_text", "operator": "equal", "operand": false }, + { "key": "selection_empty", "operator": "equal", "operand": true, "match_all": true }, + { "key": "preceding_text", "operator": "regex_match", "operand": "^[\\s>]*[-+*]\\s+$", "match_all": true }, + { "key": "following_text", "operator": "regex_match", "operand": "^\\s*$", "match_all": true } + ] + }, + { "keys": ["super+alt+t"], "command": "run_macro_file", "args": {"file": "Packages/MarkdownEditing/macros/Convert List to Task Tab.sublime-macro"}, "context": + [ + { "key": "selector", "operator": "equal", "operand": "text.html.markdown - meta.frontmatter - meta.disable-markdown - markup.raw - markup.kbd - meta.table", "match_all": true }, + { "key": "setting.auto_match_enabled", "operator": "equal", "operand": true }, + { "key": "setting.mde.list_align_text", "operator": "equal", "operand": true }, + { "key": "selection_empty", "operator": "equal", "operand": true, "match_all": true }, + { "key": "preceding_text", "operator": "regex_match", "operand": "^[\\s>]*[-+*]\\s+$", "match_all": true }, + { "key": "following_text", "operator": "regex_match", "operand": "^\\s*$", "match_all": true } + ] + }, + // Add line to current list item + { "keys": ["shift+enter"], "command": "insert_snippet", "args": {"contents": "${TM_CURRENT_LINE/^(?:\\s*((?:>\\s*)*)([-+*])(\\s+)).*/\n$1 $3/}"}, "context": + [ + { "key": "selector", "operator": "equal", "operand": "text.html.markdown - markup.raw", "match_all": true }, + { "key": "preceding_text", "operator": "regex_contains", "operand": "^[\\s>]*[-+*](?:\\s+\\S|\\s*$)", "match_all": true } + ] + }, + // Extend lists (also in block quotes) + { "keys": ["enter"], "command": "insert_snippet", "args": {"contents": "${TM_CURRENT_LINE/^(?:\\s*((?:>\\s*)*)([-+*])(\\s+)).*/\n$1$2$3/}"}, "context": + [ + { "key": "selector", "operator": "equal", "operand": "text.html.markdown - meta.frontmatter - meta.disable-markdown - markup.raw", "match_all": true }, + { "key": "preceding_text", "operator": "regex_contains", "operand": "^[\\s>]*[-+*](?:\\s+\\S|\\s*$)", "match_all": true }, + { "key": "auto_complete_visible", "operator": "equal", "operand": false } + ] + }, + { "keys": ["enter"], "command": "insert_snippet", "args": {"contents": "${TM_CURRENT_LINE/^(?:\\s*((?:>\\s*)*)([-+*])(\\s+)).*/\n$1$2$3/}"}, "context": + [ + { "key": "selector", "operator": "equal", "operand": "text.html.markdown - meta.frontmatter - meta.disable-markdown - markup.raw", "match_all": true }, + { "key": "preceding_text", "operator": "regex_contains", "operand": "^[\\s>]*[-+*](?:\\s+\\S|\\s*$)", "match_all": true }, + { "key": "setting.auto_complete_commit_on_tab" } + ] + }, + // Extend lists with GFM tasks (also in block quotes) + { "keys": ["enter"], "command": "insert_snippet", "args": {"contents": "${TM_CURRENT_LINE/^(?:\\s*((?:>\\s*)*)([-+*])(\\s+)\\[[ xX]\\](\\s+)).*/\n$1$2$3[ ]$4/}"}, "context": + [ + { "key": "selector", "operator": "equal", "operand": "text.html.markdown - meta.frontmatter - meta.disable-markdown - markup.raw", "match_all": true }, + { "key": "preceding_text", "operator": "regex_contains", "operand": "^([\\s>]*([-+*])\\s+)\\[[ xX]\\](?:\\s+\\S|\\s*$)", "match_all": true }, + { "key": "auto_complete_visible", "operator": "equal", "operand": false } + ] + }, + { "keys": ["enter"], "command": "insert_snippet", "args": {"contents": "${TM_CURRENT_LINE/^(?:\\s*((?:>\\s*)*)([-+*])(\\s+)\\[[ xX]\\](\\s+)).*/\n$1$2$3[ ]$4/}"}, "context": + [ + { "key": "selector", "operator": "equal", "operand": "text.html.markdown - meta.frontmatter - meta.disable-markdown - markup.raw", "match_all": true }, + { "key": "preceding_text", "operator": "regex_contains", "operand": "^([\\s>]*([-+*])\\s+)\\[[ xX]\\](?:\\s+\\S|\\s*$)", "match_all": true }, + { "key": "setting.auto_complete_commit_on_tab" } + ] + }, + // Extend Numbered Lists (also in block quotes) + { "keys": ["enter"], "command": "mde_number_list", "context": + [ + { "key": "selector", "operator": "equal", "operand": "text.html.markdown - meta.frontmatter - meta.disable-markdown - markup.raw", "match_all": true }, + { "key": "preceding_text", "operator": "regex_contains", "operand": "^[\\s>]*\\d+[.)]", "match_all": true }, + { "key": "auto_complete_visible", "operator": "equal", "operand": false } + ] + }, + { "keys": ["enter"], "command": "mde_number_list", "context": + [ + { "key": "selector", "operator": "equal", "operand": "text.html.markdown - meta.frontmatter - meta.disable-markdown - markup.raw", "match_all": true }, + { "key": "preceding_text", "operator": "regex_contains", "operand": "^[\\s>]*\\d+[.)]", "match_all": true }, + { "key": "setting.auto_complete_commit_on_tab" } + ] + }, + // Remove empty list item including GFM tasks + { "keys": ["enter"], "command": "run_macro_file", "args": {"file": "Packages/MarkdownEditing/macros/Remove Empty List Item.sublime-macro"}, "context": + [ + { "key": "selector", "operator": "equal", "operand": "text.html.markdown - meta.frontmatter - meta.disable-markdown - markup.raw", "match_all": true }, + { "key": "preceding_text", "operator": "regex_match", "operand": "^[\\s>]*([-+*]|\\d+[.)])(?:\\s+\\[[ xX]\\])?\\s*$", "match_all": true }, + { "key": "following_text", "operator": "regex_match", "operand": "^\\s*$", "match_all": true }, + { "key": "auto_complete_visible", "operator": "equal", "operand": false } + ] + }, + { "keys": ["enter"], "command": "run_macro_file", "args": {"file": "Packages/MarkdownEditing/macros/Remove Empty List Item.sublime-macro"}, "context": + [ + { "key": "selector", "operator": "equal", "operand": "text.html.markdown - meta.frontmatter - meta.disable-markdown - markup.raw", "match_all": true }, + { "key": "preceding_text", "operator": "regex_match", "operand": "^[\\s>]*([-+*]|\\d+[.)])(?:\\s+\\[[ xX]\\])?\\s*$", "match_all": true }, + { "key": "following_text", "operator": "regex_match", "operand": "^\\s*$", "match_all": true }, + { "key": "setting.auto_complete_commit_on_tab" } + ] + }, + { "keys": ["backspace"], "command": "run_macro_file", "args": {"file": "Packages/MarkdownEditing/macros/Remove Empty List Item.sublime-macro"}, "context": + [ + { "key": "selector", "operator": "equal", "operand": "text.html.markdown - meta.frontmatter - meta.disable-markdown - markup.raw", "match_all": true }, + { "key": "preceding_text", "operator": "regex_match", "operand": "^[\\s>]*([-+*]|\\d+[.)])(?:\\s+\\[[ xX]\\])?\\s?$", "match_all": true }, + { "key": "following_text", "operator": "regex_match", "operand": "^\\s*$", "match_all": true } + ] + }, + // Join content of next into current line after removing its leading blockquote, list and GFM task punctuation + { "keys": ["delete"], "command": "mde_join_lines", "context": + [ + { "key": "selector", "operator": "equal", "operand": "text.html.markdown markup.quote, text.html.markdown markup.list" }, + { "key": "selection_empty", "operator": "equal", "operand": true, "match_all": true }, + { "key": "following_text", "operator": "regex_match", "operand": "^$", "match_all": true } + ] + }, + { "keys": ["ctrl+shift+j"], "command": "mde_join_lines", "context": + [ + { "key": "selector", "operator": "equal", "operand": "text.html.markdown markup.quote, text.html.markdown markup.list" } + ] + }, + // Indent list item if caret is in front of bullets + { "keys": ["tab"], "command": "mde_indent_list_item", "context": + [ + { "key": "selector", "operator": "equal", "operand": "text.html.markdown - meta.frontmatter - meta.disable-markdown - markup.raw", "match_all": true }, + { "key": "selection_empty", "operator": "equal", "operand": true, "match_all": true }, + { "key": "has_next_field", "operator": "equal", "operand": false }, + { "key": "overlay_visible", "operator": "equal", "operand": false }, + { "key": "preceding_text", "operator": "regex_match", "operand": "^[\\s>]*$", "match_all": true }, + { "key": "following_text", "operator": "regex_contains", "operand": "^\\s*[-+*]\\s", "match_all": true } + ] + }, + // Indent list item, if caret is directly behind bullet only if followed by whitespace + // Hitting "tab" directly after new list bullet should insert \t otherwise + { "keys": ["tab"], "command": "mde_indent_list_item", "context": + [ + { "key": "selector", "operator": "equal", "operand": "text.html.markdown - meta.frontmatter - meta.disable-markdown - markup.raw", "match_all": true }, + { "key": "selection_empty", "operator": "equal", "operand": true, "match_all": true }, + { "key": "has_next_field", "operator": "equal", "operand": false }, + { "key": "overlay_visible", "operator": "equal", "operand": false }, + { "key": "preceding_text", "operator": "regex_match", "operand": "^[\\s>]*[-+*]$", "match_all": true }, + { "key": "following_text", "operator": "regex_contains", "operand": "^\\s", "match_all": true } + ] + }, + // Indent list item if caret is behind bullets + { "keys": ["tab"], "command": "mde_indent_list_item", "context": + [ + { "key": "selector", "operator": "equal", "operand": "text.html.markdown - meta.frontmatter - meta.disable-markdown - markup.raw", "match_all": true }, + { "key": "selection_empty", "operator": "equal", "operand": true, "match_all": true }, + { "key": "has_next_field", "operator": "equal", "operand": false }, + { "key": "overlay_visible", "operator": "equal", "operand": false }, + { "key": "preceding_text", "operator": "regex_match", "operand": "^[\\s>]*[-+*]\\s*$", "match_all": true }, + { "key": "following_text", "operator": "not_regex_match", "operand": "(?:-{2,}|={2,}|[+*])", "match_all": true } + ] + }, + // Indent selected list items + { "keys": ["tab"], "command": "mde_indent_list_item", "context": + [ + { "key": "selector", "operator": "equal", "operand": "text.html.markdown - meta.frontmatter - meta.disable-markdown - markup.raw", "match_all": true }, + { "key": "selection_empty", "operator": "equal", "operand": false, "match_all": true }, + { "key": "has_next_field", "operator": "equal", "operand": false }, + { "key": "overlay_visible", "operator": "equal", "operand": false } + ] + }, + // Unindent list item no matter of caret position if `shift_tab_unindent` is set + { "keys": ["shift+tab"], "command": "mde_unindent_list_item", "context": + [ + { "key": "selector", "operator": "equal", "operand": "text.html.markdown", "match_all": true }, + { "key": "setting.shift_tab_unindent", "operator": "equal", "operand": true }, + { "key": "has_prev_field", "operator": "equal", "operand": false }, + { "key": "overlay_visible", "operator": "equal", "operand": false }, + { "key": "preceding_text", "operator": "regex_contains", "operand": "^[\\s>]*[-+*]\\s", "match_all": true } + ] + }, + // Unindent list item if caret is in front of bullets + { "keys": ["shift+tab"], "command": "mde_unindent_list_item", "context": + [ + { "key": "selector", "operator": "equal", "operand": "text.html.markdown", "match_all": true }, + { "key": "has_prev_field", "operator": "equal", "operand": false }, + { "key": "overlay_visible", "operator": "equal", "operand": false }, + { "key": "preceding_text", "operator": "regex_match", "operand": "^[\\s>]*$", "match_all": true }, + { "key": "following_text", "operator": "regex_contains", "operand": "^\\s*[-+*]\\s", "match_all": true } + ] + }, + // Unindent list item if caret is behind bullets + { "keys": ["shift+tab"], "command": "mde_unindent_list_item", "context": + [ + { "key": "selector", "operator": "equal", "operand": "text.html.markdown", "match_all": true }, + { "key": "has_prev_field", "operator": "equal", "operand": false }, + { "key": "overlay_visible", "operator": "equal", "operand": false }, + { "key": "preceding_text", "operator": "regex_match", "operand": "^[\\s>]*[-+*]\\s*$", "match_all": true }, + { "key": "following_text", "operator": "not_regex_match", "operand": "(?:-{2,}|={2,})", "match_all": true } + ] + }, + // Unindent list item if caret is at eol + { "keys": ["shift+tab"], "command": "mde_unindent_list_item", "context": + [ + { "key": "selector", "operator": "equal", "operand": "text.html.markdown markup.list", "match_all": true }, + { "key": "has_prev_field", "operator": "equal", "operand": false }, + { "key": "overlay_visible", "operator": "equal", "operand": false }, + { "key": "preceding_text", "operator": "regex_contains", "operand": "^[\\s>]*[-+*]\\s", "match_all": true }, + { "key": "following_text", "operator": "regex_match", "operand": "^$" } + ] + }, + // Unindent selected list items + { "keys": ["shift+tab"], "command": "mde_unindent_list_item", "context": + [ + { "key": "selector", "operator": "equal", "operand": "text.html.markdown markup.list", "match_all": true }, + { "key": "selection_empty", "operator": "equal", "operand": false, "match_all": true }, + { "key": "has_prev_field", "operator": "equal", "operand": false }, + { "key": "overlay_visible", "operator": "equal", "operand": false } + ] + }, + // Toggle GFM tasks + { "keys": ["alt+x"], "command": "mde_toggle_task_list_item", "context": + [ + { "key": "selector", "operator": "equal", "operand": "text.html.markdown & (markup.list | markup.quote)", "match_all": true } + ] + }, + + // + // Quotes + // + + // Convert to blockquote + { "keys": [">"], "command": "run_macro_file", "args": {"file": "Packages/MarkdownEditing/macros/Convert to Blockquote.sublime-macro"}, "context": + [ + { "key": "selector", "operator": "equal", "operand": "text.html.markdown - meta.frontmatter - meta.disable-markdown - markup.raw - markup.kbd", "match_all": true }, + { "key": "selection_empty", "operator": "equal", "operand": false, "match_all": true } + ] + }, + // Extend blockquote (ignore headings, lists and tasks) + { "keys": ["enter"], "command": "insert_snippet", "args": {"contents": "${TM_CURRENT_LINE/^\\s*((?:>\\s*)*(?:>\\s?)).*/\n$1/}"}, "context": + [ + { "key": "selector", "operator": "equal", "operand": "text.html.markdown markup.quote", "match_all": true }, + { "key": "preceding_text", "operator": "regex_contains", "operand": "^\\s*(?:>\\s*)+(?![-+*>#\\s]|\\d+[.)])", "match_all": true }, + { "key": "auto_complete_visible", "operator": "equal", "operand": false } + ] + }, + { "keys": ["enter"], "command": "insert_snippet", "args": {"contents": "${TM_CURRENT_LINE/^\\s*((?:>\\s*)*(?:>\\s?)).*/\n$1/}"}, "context": + [ + { "key": "selector", "operator": "equal", "operand": "text.html.markdown markup.quote", "match_all": true }, + { "key": "preceding_text", "operator": "regex_contains", "operand": "^\\s*(?:>\\s*)+(?![-+*>#\\s]|\\d+[.)])", "match_all": true }, + { "key": "setting.auto_complete_commit_on_tab" } + ] + }, + // Remove empty blockquote line + // { "keys": ["enter"], "command": "run_macro_file", "args": {"file": "Packages/MarkdownEditing/macros/Remove Empty Blockquote Line.sublime-macro"}, "context": + // [ + // { "key": "selector", "operator": "equal", "operand": "text.html.markdown markup.quote", "match_all": true }, + // { "key": "preceding_text", "operator": "regex_match", "operand": "^\\s*(>\\s*)+$", "match_all": true }, + // { "key": "following_text", "operator": "regex_match", "operand": "^\\s*$", "match_all": true }, + // { "key": "auto_complete_visible", "operator": "equal", "operand": false } + // ] + // }, + // { "keys": ["enter"], "command": "run_macro_file", "args": {"file": "Packages/MarkdownEditing/macros/Remove Empty Blockquote Line.sublime-macro"}, "context": + // [ + // { "key": "selector", "operator": "equal", "operand": "text.html.markdown markup.quote", "match_all": true }, + // { "key": "preceding_text", "operator": "regex_match", "operand": "^\\s*(>\\s*)+$", "match_all": true }, + // { "key": "following_text", "operator": "regex_match", "operand": "^\\s*$", "match_all": true }, + // { "key": "setting.auto_complete_commit_on_tab" } + // ] + // }, + { "keys": ["backspace"], "command": "run_macro_file", "args": {"file": "Packages/MarkdownEditing/macros/Remove Empty Blockquote Line.sublime-macro"}, "context": + [ + { "key": "selector", "operator": "equal", "operand": "text.html.markdown markup.quote", "match_all": true }, + { "key": "preceding_text", "operator": "regex_match", "operand": "^\\s*(>\\s*)*(>\\s?)$", "match_all": true }, + { "key": "following_text", "operator": "regex_match", "operand": "^\\s*$", "match_all": true } + ] + }, + // Indent blockquote + { "keys": ["super+shift+."], "command": "mde_indent_quote", "context": + [ + { "key": "selector", "operator": "equal", "operand": "text.html.markdown", "match_all": true } + ] + }, + // Unindent blockquote + { "keys": ["super+shift+,"], "command": "mde_unindent_quote", "context": + [ + { "key": "selector", "operator": "equal", "operand": "text.html.markdown", "match_all": true }, + { "key": "preceding_text", "operator": "regex_contains", "operand": "(> )+", "match_all": true } + ] + }, + + // + // References + // + + // Surround with <> on URLs, regex copied from https://mathiasbynens.be/demo/url-regex, @diegoperini (502 chars) + { "keys": ["<"], "command": "insert_snippet", "args": {"contents": "<${0:$SELECTION}>"}, "context": + [ + { "key": "selector", "operator": "equal", "operand": "text.html.markdown - meta.frontmatter - meta.disable-markdown - markup.raw - markup.kbd", "match_all": true }, + { "key": "setting.auto_match_enabled", "operator": "equal", "operand": true }, + { "key": "selection_empty", "operator": "equal", "operand": false, "match_all": true }, + { "key": "text", "operator": "regex_match", "operand": "(?:(?:https?|ftp)://)(?:\\S+(?::\\S*)?@)?(?:(?!10(?:\\.\\d{1,3}){3})(?!127(?:\\.\\d{1,3}){3})(?!169\\.254(?:\\.\\d{1,3}){2})(?!192\\.168(?:\\.\\d{1,3}){2})(?!172\\.(?:1[6-9]|2\\d|3[0-1])(?:\\.\\d{1,3}){2})(?:[1-9]\\d?|1\\d\\d|2[01]\\d|22[0-3])(?:\\.(?:1?\\d{1,2}|2[0-4]\\d|25[0-5])){2}(?:\\.(?:[1-9]\\d?|1\\d\\d|2[0-4]\\d|25[0-4]))|(?:(?:[a-z\\x{00a1}-\\x{ffff}0-9]+-?)*[a-z\\x{00a1}-\\x{ffff}0-9]+)(?:\\.(?:[a-z\\x{00a1}-\\x{ffff}0-9]+-?)*[a-z\\x{00a1}-\\x{ffff}0-9]+)*(?:\\.(?:[a-z\\x{00a1}-\\x{ffff}]{2,})))(?::\\d{2,5})?(?:/[^\\s]*)?", "match_all": true } + ] + }, + // modify [] pairing so that selection is removed after pairing, ready for [] or () + { "keys": ["["], "command": "insert_snippet", "args": {"contents": "[$SELECTION]$0"}, "context": + [ + { "key": "selector", "operator": "equal", "operand": "text.html.markdown - meta.frontmatter - meta.disable-markdown - markup.raw - markup.kbd", "match_all": true }, + { "key": "setting.auto_match_enabled", "operator": "equal", "operand": true }, + { "key": "selection_empty", "operator": "equal", "operand": false, "match_all": true } + ] + }, + // inline image insertion + { "keys": ["super+shift+k"], "command": "mde_reference_new_inline_image", "context": + [ + { "key": "selector", "operator": "equal", "operand": "text.html.markdown", "match_all": true }, + { "key": "setting.mde.keymap_disable.reference_new_inline_image", "operator": "not_equal", "operand": true } + ] + }, + // run paste as link command on selected text + { "keys": ["super+alt+v"], "command": "mde_reference_new_inline_link", "context": + [ + { "key": "selector", "operator": "equal", "operand": "text.html.markdown", "match_all": true }, + { "key": "setting.mde.keymap_disable.reference_new_inline_link", "operator": "not_equal", "operand": true } + ] + }, + // create new footnote + { "keys": ["alt+shift+6"], "command": "mde_reference_new_footnote", "context": + [ + { "key": "selector", "operator": "equal", "operand": "text.html.markdown", "match_all": true }, + { "key": "setting.mde.keymap_disable.reference_new_footnote", "operator": "not_equal", "operand": true } + ] + }, + // create new reference + { "keys": ["super+alt+r"], "command": "mde_reference_new_reference", "context": + [ + { "key": "selector", "operator": "equal", "operand": "text.html.markdown", "match_all": true }, + { "key": "setting.mde.keymap_disable.reference_new_reference", "operator": "not_equal", "operand": true } + ] + }, + // extend numbered reference if auto completion panel is not visible + { "keys": ["enter"], "command": "mde_add_numbered_reference_definition", "context": + [ + { "key": "selector", "operator": "equal", "operand": "text.html.markdown - meta.frontmatter - meta.disable-markdown - markup.raw", "match_all": true }, + { "key": "preceding_text", "operator": "regex_contains", "operand": "^\\s*\\[.*\\d+\\]:", "match_all": true }, + { "key": "auto_complete_visible", "operand": false } + ] + }, + // extend numbered reference if auto-completions are commited via tab only + { "keys": ["enter"], "command": "mde_add_numbered_reference_definition", "context": + [ + { "key": "selector", "operator": "equal", "operand": "text.html.markdown - meta.frontmatter - meta.disable-markdown - markup.raw", "match_all": true }, + { "key": "preceding_text", "operator": "regex_contains", "operand": "^\\s*\\[.*\\d+\\]:", "match_all": true }, + { "key": "setting.auto_complete_commit_on_tab" } + ] + }, + // jump to reference + { "keys": ["super+ctrl+shift+l"], "command": "mde_reference_jump", "context": + [ + { "key": "selector", "operator": "equal", "operand": "text.html.markdown", "match_all": true }, + { "key": "setting.mde.keymap_disable.reference_jump", "operator": "not_equal", "operand": true } + ] + }, + // organize references + { "keys": ["super+ctrl+s"], "command": "mde_reference_organize", "context": + [ + { "key": "selector", "operator": "equal", "operand": "text.html.markdown", "match_all": true }, + { "key": "setting.mde.keymap_disable.reference_organize", "operator": "not_equal", "operand": true } + ] + }, + + // + // CriticMarkup + // + + // insert new addition or mark selection for addition + { "keys": ["super+alt+c", "super+alt+a"], "command": "insert_snippet", "args": {"name": "Packages/MarkdownEditing/snippets/Critic Addition.sublime-snippet"}, "context": + [ + { "key": "selector", "operator": "equal", "operand": "text.html.markdown - meta.frontmatter - meta.disable-markdown - markup.critic - meta.code-fence - markup.raw - markup.kbd", "match_all": true } + ] + }, + // commit addition + { "keys": ["super+alt+enter"], "command": "run_macro_file", "args": {"file": "Packages/MarkdownEditing/macros/Commit Critic Addition.sublime-macro"}, "context": + [ + { "key": "selector", "operator": "equal", "operand": "text.html.markdown markup.critic.addition", "match_all": true }, + { "key": "selection_empty", "operator": "equal", "operand": true, "match_all": false } + ] + }, + // discard addition + { "keys": ["super+alt+backspace"], "command": "run_macro_file", "args": {"file": "Packages/MarkdownEditing/macros/Discard Critic Addition.sublime-macro"}, "context": + [ + { "key": "selector", "operator": "equal", "operand": "text.html.markdown markup.critic.addition", "match_all": true }, + { "key": "selection_empty", "operator": "equal", "operand": true, "match_all": false } + ] + }, + + // insert comment or convert selection into comment + { "keys": ["super+alt+c", "super+alt+c"], "command": "insert_snippet", "args": {"name": "Packages/MarkdownEditing/snippets/Critic Comment.sublime-snippet"}, "context": + [ + { "key": "selector", "operator": "equal", "operand": "text.html.markdown - meta.frontmatter - meta.disable-markdown - markup.critic - meta.code-fence - markup.raw - markup.kbd", "match_all": true } + ] + }, + // remove comment + { "keys": ["super+alt+c", "super+alt+c"], "command": "run_macro_file", "args": {"file": "Packages/MarkdownEditing/macros/Discard Critic Comment.sublime-macro"}, "context": + [ + { "key": "selector", "operator": "equal", "operand": "text.html.markdown markup.critic.comment", "match_all": true }, + { "key": "selection_empty", "operator": "equal", "operand": true, "match_all": false } + ] + }, + { "keys": ["super+alt+enter"], "command": "run_macro_file", "args": {"file": "Packages/MarkdownEditing/macros/Discard Critic Comment.sublime-macro"}, "context": + [ + { "key": "selector", "operator": "equal", "operand": "text.html.markdown markup.critic.comment", "match_all": true }, + { "key": "selection_empty", "operator": "equal", "operand": true, "match_all": false } + ] + }, + { "keys": ["super+alt+backspace"], "command": "run_macro_file", "args": {"file": "Packages/MarkdownEditing/macros/Discard Critic Comment.sublime-macro"}, "context": + [ + { "key": "selector", "operator": "equal", "operand": "text.html.markdown markup.critic.comment", "match_all": true }, + { "key": "selection_empty", "operator": "equal", "operand": true, "match_all": false } + ] + }, + + // mark word for deletion + { "keys": ["super+alt+c", "super+alt+d"], "command": "run_macro_file", "args": {"file": "Packages/MarkdownEditing/macros/Transform Word - Critic Deletion.sublime-macro"}, "context": + [ + { "key": "selector", "operator": "equal", "operand": "text.html.markdown - meta.frontmatter - meta.disable-markdown - markup.critic - meta.code-fence - markup.raw - markup.kbd", "match_all": true }, + { "key": "selection_empty", "operator": "equal", "operand": true, "match_all": false } + ] + }, + // mark selection for deletion + { "keys": ["super+alt+c", "super+alt+d"], "command": "insert_snippet", "args": {"name": "Packages/MarkdownEditing/snippets/Critic Deletion.sublime-snippet"}, "context": + [ + { "key": "selector", "operator": "equal", "operand": "text.html.markdown - meta.frontmatter - meta.disable-markdown - markup.critic - meta.code-fence - markup.raw - markup.kbd", "match_all": true }, + { "key": "selection_empty", "operator": "equal", "operand": false, "match_all": true } + ] + }, + // commit deletion + { "keys": ["super+alt+enter"], "command": "run_macro_file", "args": {"file": "Packages/MarkdownEditing/macros/Commit Critic Deletion.sublime-macro"}, "context": + [ + { "key": "selector", "operator": "equal", "operand": "text.html.markdown markup.critic.deletion", "match_all": true }, + { "key": "selection_empty", "operator": "equal", "operand": true, "match_all": false } + ] + }, + // discard deletion + { "keys": ["super+alt+backspace"], "command": "run_macro_file", "args": {"file": "Packages/MarkdownEditing/macros/Discard Critic Deletion.sublime-macro"}, "context": + [ + { "key": "selector", "operator": "equal", "operand": "text.html.markdown markup.critic.deletion", "match_all": true }, + { "key": "selection_empty", "operator": "equal", "operand": true, "match_all": false } + ] + }, + + // mark word for highlight + { "keys": ["super+alt+c", "super+alt+h"], "command": "run_macro_file", "args": {"file": "Packages/MarkdownEditing/macros/Transform Word - Critic Highlight.sublime-macro"}, "context": + [ + { "key": "selector", "operator": "equal", "operand": "text.html.markdown - meta.frontmatter - meta.disable-markdown - markup.critic - meta.code-fence - markup.raw - markup.kbd", "match_all": true }, + { "key": "selection_empty", "operator": "equal", "operand": true, "match_all": false } + ] + }, + // mark selection for highlighting + { "keys": ["super+alt+c", "super+alt+h"], "command": "insert_snippet", "args": {"name": "Packages/MarkdownEditing/snippets/Critic Highlight.sublime-snippet"}, "context": + [ + { "key": "selector", "operator": "equal", "operand": "text.html.markdown - meta.frontmatter - meta.disable-markdown - markup.critic - meta.code-fence - markup.raw - markup.kbd", "match_all": true }, + { "key": "selection_empty", "operator": "equal", "operand": false, "match_all": true } + ] + }, + // remove highlight + { "keys": ["super+alt+enter"], "command": "run_macro_file", "args": {"file": "Packages/MarkdownEditing/macros/Discard Critic Highlight.sublime-macro"}, "context": + [ + { "key": "selector", "operator": "equal", "operand": "text.html.markdown markup.critic.highlight", "match_all": true }, + { "key": "selection_empty", "operator": "equal", "operand": true, "match_all": false } + ] + }, + { "keys": ["super+alt+backspace"], "command": "run_macro_file", "args": {"file": "Packages/MarkdownEditing/macros/Discard Critic Highlight.sublime-macro"}, "context": + [ + { "key": "selector", "operator": "equal", "operand": "text.html.markdown markup.critic.highlight", "match_all": true }, + { "key": "selection_empty", "operator": "equal", "operand": true, "match_all": false } + ] + }, + + // mark word for substitution + { "keys": ["super+alt+c", "super+alt+s"], "command": "run_macro_file", "args": {"file": "Packages/MarkdownEditing/macros/Transform Word - Critic Substitution.sublime-macro"}, "context": + [ + { "key": "selector", "operator": "equal", "operand": "text.html.markdown - meta.frontmatter - meta.disable-markdown - markup.critic - meta.code-fence - markup.raw - markup.kbd", "match_all": true }, + { "key": "selection_empty", "operator": "equal", "operand": true, "match_all": false } + ] + }, + // mark selection for substitution + { "keys": ["super+alt+c", "super+alt+s"], "command": "insert_snippet", "args": {"name": "Packages/MarkdownEditing/snippets/Critic Substitution.sublime-snippet"}, "context": + [ + { "key": "selector", "operator": "equal", "operand": "text.html.markdown - meta.frontmatter - meta.disable-markdown - markup.critic - meta.code-fence - markup.raw - markup.kbd", "match_all": true }, + { "key": "selection_empty", "operator": "equal", "operand": false, "match_all": true } + ] + }, + // commit substitution + { "keys": ["super+alt+enter"], "command": "run_macro_file", "args": {"file": "Packages/MarkdownEditing/macros/Commit Critic Substitution.sublime-macro"}, "context": + [ + { "key": "selector", "operator": "equal", "operand": "text.html.markdown markup.critic.substitution", "match_all": true }, + { "key": "selection_empty", "operator": "equal", "operand": true, "match_all": false } + ] + }, + // discard substitution + { "keys": ["super+alt+backspace"], "command": "run_macro_file", "args": {"file": "Packages/MarkdownEditing/macros/Discard Critic Substitution.sublime-macro"}, "context": + [ + { "key": "selector", "operator": "equal", "operand": "text.html.markdown markup.critic.substitution", "match_all": true }, + { "key": "selection_empty", "operator": "equal", "operand": true, "match_all": false } + ] + }, + + // + // Wiki + // + + { "keys": ["super+shift+h"], "command": "mde_open_home_page", "context": + [ + { "key": "selector", "operator": "equal", "operand": "text.html.markdown", "match_all": true }, + { "key": "setting.mde.keymap_disable.open_home_page", "operator": "not_equal", "operand": true } + ] + }, + { "keys": ["super+shift+d"], "command": "mde_open_page", "context": + [ + { "key": "selector", "operator": "equal", "operand": "meta.link.wiki.markdown", "match_all": true }, + { "key": "setting.mde.keymap_disable.open_page", "operator": "not_equal", "operand": true } + ] + }, + { "keys": ["super+shift+d"], "command": "mde_make_page_reference", "context": + [ + { "key": "selector", "operator": "equal", "operand": "text.html.markdown - (meta.link.wiki | markup.underline.link)", "match_all": true }, + { "key": "setting.mde.keymap_disable.make_page_reference", "operator": "not_equal", "operand": true } + ] + }, + { "keys": ["super+shift+x"], "command": "mde_list_back_links", "context": + [ + { "key": "selector", "operator": "equal", "operand": "text.html.markdown", "match_all": true }, + { "key": "setting.mde.keymap_disable.list_back_links", "operator": "not_equal", "operand": true } + ] + }, + { "keys": ["super+shift+j"], "command": "mde_open_journal", "context": + [ + { "key": "selector", "operator": "equal", "operand": "text.html.markdown", "match_all": true }, + { "key": "setting.mde.keymap_disable.open_journal", "operator": "not_equal", "operand": true } + ] + } ] diff --git a/Default (Windows).sublime-keymap b/Default (Windows).sublime-keymap index 43bd5fbf..32fb09c1 100644 --- a/Default (Windows).sublime-keymap +++ b/Default (Windows).sublime-keymap @@ -1,699 +1,1193 @@ [ - // selection pairing with *, _ and ` - { "keys": ["*"], "command": "insert_snippet", "args": {"contents": "*$0*"}, "context": - [ - { "key": "setting.auto_match_enabled", "operator": "equal", "operand": true }, - { "key": "selection_empty", "operator": "equal", "operand": true, "match_all": true }, - { "key": "following_text", "operator": "regex_contains", "operand": "^(?:\t| |\\)|]|\\}|$)", "match_all": true }, - { "key": "preceding_text", "operator": "not_regex_contains", "operand": "['a-zA-Z0-9_*]$", "match_all": true }, - { "key": "eol_selector", "operator": "not_equal", "operand": "string.quoted.single", "match_all": true }, - { "key": "selector", "operator": "equal", "operand": "text.html.markdown", "match_all": true }, - { "key": "selector", "operator": "not_equal", "operand": "markup.raw", "match_all": true } - ] - }, - { "keys": ["*"], "command": "run_macro_file", "args": {"file": "Packages/MarkdownEditing/macros/Skip Closing Character.sublime-macro"}, "context": - [ - { "key": "selection_empty", "operator": "equal", "operand": true, "match_all": true }, - { "key": "following_text", "operator": "regex_contains", "operand": "^\\*", "match_all": true }, - { "key": "selector", "operator": "equal", "operand": "text.html.markdown", "match_all": true }, - { "key": "selector", "operator": "not_equal", "operand": "markup.raw", "match_all": true } - ] - }, - { "keys": ["*"], "command": "insert_snippet", "args": {"contents": "*${0:$SELECTION}*"}, "context": - [ - { "key": "setting.auto_match_enabled", "operator": "equal", "operand": true }, - { "key": "selection_empty", "operator": "equal", "operand": false, "match_all": true }, - { "key": "selector", "operator": "equal", "operand": "text.html.markdown", "match_all": true }, - { "key": "selector", "operator": "not_equal", "operand": "markup.raw", "match_all": true } - ] - }, - { "keys": ["backspace"], "command": "run_macro_file", "args": {"file": "Packages/Default/Delete Left Right.sublime-macro"}, "context": - [ - { "key": "setting.auto_match_enabled", "operator": "equal", "operand": true }, - { "key": "selection_empty", "operator": "equal", "operand": true, "match_all": true }, - { "key": "preceding_text", "operator": "regex_contains", "operand": "\\*$", "match_all": true }, - { "key": "following_text", "operator": "regex_contains", "operand": "^\\*", "match_all": true }, - { "key": "selector", "operator": "equal", "operand": "text.html.markdown", "match_all": true }, - { "key": "selector", "operator": "not_equal", "operand": "markup.raw", "match_all": true } - ] - }, - { "keys": [" "], "command": "run_macro_file", "args": {"file": "Packages/MarkdownEditing/macros/Start List Item.sublime-macro"}, "context": - [ - { "key": "setting.auto_match_enabled", "operator": "equal", "operand": true }, - { "key": "selection_empty", "operator": "equal", "operand": true, "match_all": true }, - { "key": "preceding_text", "operator": "regex_contains", "operand": "\\*$", "match_all": true }, - { "key": "following_text", "operator": "regex_contains", "operand": "^\\*", "match_all": true }, - { "key": "selector", "operator": "equal", "operand": "text.html.markdown", "match_all": true }, - { "key": "selector", "operator": "not_equal", "operand": "markup.raw", "match_all": true } - ] - }, - { "keys": ["tab"], "command": "run_macro_file", "args": {"file": "Packages/MarkdownEditing/macros/Start List Item Tab.sublime-macro"}, "context": - [ - { "key": "setting.auto_match_enabled", "operator": "equal", "operand": true }, - { "key": "selection_empty", "operator": "equal", "operand": true, "match_all": true }, - { "key": "preceding_text", "operator": "regex_contains", "operand": "\\*$", "match_all": true }, - { "key": "following_text", "operator": "regex_contains", "operand": "^\\*", "match_all": true }, - { "key": "selector", "operator": "equal", "operand": "text.html.markdown", "match_all": true }, - { "key": "selector", "operator": "not_equal", "operand": "markup.raw", "match_all": true } - ] - }, - { "keys": ["tab"], "command": "indent_list_item", "context": - [ - { "key": "selection_empty", "operator": "equal", "operand": true, "match_all": true }, - { "key": "preceding_text", "operator": "regex_contains", "operand": "^\\s*(>\\s*)?[*+\\-]\\s+$", "match_all": true }, - { "key": "following_text", "operator": "regex_contains", "operand": "^$", "match_all": true }, - { "key": "selector", "operator": "equal", "operand": "text.html.markdown", "match_all": true }, - { "key": "selector", "operator": "not_equal", "operand": "markup.raw", "match_all": true } - ] - }, - { "keys": ["tab"], "command": "indent_list_multiitem", "context": - [ - { "key": "selection_empty", "operator": "equal", "operand": false, "match_all": true }, - { "key": "selector", "operator": "equal", "operand": "text.html.markdown", "match_all": true }, - { "key": "selector", "operator": "equal", "operand": "markup.list", "match_all": true } - ] - }, - { "keys": ["shift+tab"], "command": "indent_list_item", "args": {"reverse": true}, "context": - [ - { "key": "selection_empty", "operator": "equal", "operand": true, "match_all": true }, - { "key": "preceding_text", "operator": "regex_contains", "operand": "^\\s*(>\\s*)?[*+\\-]\\s+$", "match_all": true }, - { "key": "following_text", "operator": "regex_contains", "operand": "^$", "match_all": true }, - { "key": "selector", "operator": "equal", "operand": "text.html.markdown", "match_all": true }, - { "key": "selector", "operator": "not_equal", "operand": "markup.raw", "match_all": true } - ] - }, - { "keys": ["shift+tab"], "command": "indent_list_multiitem", "args": {"reverse": true}, "context": - [ - { "key": "selection_empty", "operator": "equal", "operand": false, "match_all": true }, - { "key": "selector", "operator": "equal", "operand": "text.html.markdown", "match_all": true }, - { "key": "selector", "operator": "equal", "operand": "markup.list", "match_all": true } - ] - }, - { "keys": ["_"], "command": "insert_snippet", "args": {"contents": "_$0_"}, "context": - [ - { "key": "setting.auto_match_enabled", "operator": "equal", "operand": true }, - { "key": "selection_empty", "operator": "equal", "operand": true, "match_all": true }, - { "key": "following_text", "operator": "regex_contains", "operand": "^(?:\t| |\\)|]|\\}|$)", "match_all": true }, - { "key": "preceding_text", "operator": "not_regex_contains", "operand": "['a-zA-Z0-9_]$", "match_all": true }, - { "key": "eol_selector", "operator": "not_equal", "operand": "string.quoted.single", "match_all": true }, - { "key": "selector", "operator": "equal", "operand": "text.html.markdown", "match_all": true }, - { "key": "selector", "operator": "not_equal", "operand": "markup.raw", "match_all": true } - ] - }, - { "keys": ["_"], "command": "insert_snippet", "args": {"contents": "_${0:$SELECTION}_"}, "context": - [ - { "key": "setting.auto_match_enabled", "operator": "equal", "operand": true }, - { "key": "selection_empty", "operator": "equal", "operand": false, "match_all": true }, - { "key": "selector", "operator": "equal", "operand": "text.html.markdown", "match_all": true }, - { "key": "selector", "operator": "not_equal", "operand": "markup.raw", "match_all": true } - ] - }, - { "keys": ["_"], "command": "run_macro_file", "args": {"file": "Packages/MarkdownEditing/macros/Skip Closing Character.sublime-macro"}, "context": - [ - { "key": "selection_empty", "operator": "equal", "operand": true, "match_all": true }, - { "key": "following_text", "operator": "regex_contains", "operand": "^_", "match_all": true }, - { "key": "selector", "operator": "equal", "operand": "text.html.markdown", "match_all": true }, - { "key": "selector", "operator": "not_equal", "operand": "markup.raw", "match_all": true } - ] - }, - { "keys": ["backspace"], "command": "run_macro_file", "args": {"file": "Packages/Default/Delete Left Right.sublime-macro"}, "context": - [ - { "key": "setting.auto_match_enabled", "operator": "equal", "operand": true }, - { "key": "selection_empty", "operator": "equal", "operand": true, "match_all": true }, - { "key": "preceding_text", "operator": "regex_contains", "operand": "_$", "match_all": true }, - { "key": "following_text", "operator": "regex_contains", "operand": "^_", "match_all": true }, - { "key": "selector", "operator": "equal", "operand": "text.html.markdown", "match_all": true }, - { "key": "selector", "operator": "not_equal", "operand": "markup.raw", "match_all": true } - ] - }, - { "keys": [" "], "command": "run_macro_file", "args": {"file": "Packages/MarkdownEditing/macros/Start List Item.sublime-macro"}, "context": - [ - { "key": "setting.auto_match_enabled", "operator": "equal", "operand": true }, - { "key": "selection_empty", "operator": "equal", "operand": true, "match_all": true }, - { "key": "preceding_text", "operator": "regex_contains", "operand": "\\_$", "match_all": true }, - { "key": "following_text", "operator": "regex_contains", "operand": "^\\_", "match_all": true }, - { "key": "selector", "operator": "equal", "operand": "text.html.markdown", "match_all": true }, - { "key": "selector", "operator": "not_equal", "operand": "markup.raw", "match_all": true } - ] - }, - { "keys": ["`"], "command": "insert_snippet", "args": {"contents": "`$0`"}, "context": - [ - { "key": "setting.auto_match_enabled", "operator": "equal", "operand": true }, - { "key": "selection_empty", "operator": "equal", "operand": true, "match_all": true }, - { "key": "following_text", "operator": "regex_contains", "operand": "^(?:\t| |\\)|]|\\}|$)", "match_all": true }, - { "key": "preceding_text", "operator": "not_regex_contains", "operand": "['a-zA-Z0-9_`]$", "match_all": true }, - { "key": "eol_selector", "operator": "not_equal", "operand": "string.quoted.single", "match_all": true }, - { "key": "selector", "operator": "equal", "operand": "text.html.markdown", "match_all": true } - ] - }, - { "keys": ["`"], "command": "insert_snippet", "args": {"contents": "`${0:$SELECTION}`"}, "context": - [ - { "key": "setting.auto_match_enabled", "operator": "equal", "operand": true }, - { "key": "selection_empty", "operator": "equal", "operand": false, "match_all": true }, - { "key": "selector", "operator": "equal", "operand": "text.html.markdown", "match_all": true } - ] - }, - { "keys": ["`"], "command": "run_macro_file", "args": {"file": "Packages/MarkdownEditing/macros/Skip Closing Character.sublime-macro"}, "context": - [ - { "key": "selection_empty", "operator": "equal", "operand": true, "match_all": true }, - { "key": "following_text", "operator": "regex_contains", "operand": "^`", "match_all": true }, - { "key": "selector", "operator": "equal", "operand": "text.html.markdown", "match_all": true } - ] - }, - { "keys": ["~"], "command": "insert_snippet", "args": {"contents": "~~${0:$SELECTION}~~"}, "context": - [ - { "key": "setting.auto_match_enabled", "operator": "equal", "operand": true }, - { "key": "selection_empty", "operator": "equal", "operand": false, "match_all": true }, - { "key": "selector", "operator": "equal", "operand": "text.html.markdown", "match_all": true }, - { "key": "selector", "operator": "not_equal", "operand": "markup.raw", "match_all": true } - ] - }, - { "keys": ["backspace"], "command": "run_macro_file", "args": {"file": "Packages/Default/Delete Left Right.sublime-macro"}, "context": - [ - { "key": "setting.auto_match_enabled", "operator": "equal", "operand": true }, - { "key": "selection_empty", "operator": "equal", "operand": true, "match_all": true }, - { "key": "preceding_text", "operator": "regex_contains", "operand": "`$", "match_all": true }, - { "key": "following_text", "operator": "regex_contains", "operand": "^`", "match_all": true }, - { "key": "selector", "operator": "equal", "operand": "text.html.markdown", "match_all": true } - ] - }, - // Bold on Alt + B - { "keys": ["alt+b"], "command": "run_macro_file", "args": {"file": "Packages/MarkdownEditing/macros/Transform Word - Bold.sublime-macro"}, "context": - [ - { "key": "selection_empty", "operator": "equal", "operand": true, "match_all": true }, - { "key": "selector", "operator": "equal", "operand": "text.html.markdown", "match_all": true } - ] - }, - { "keys": ["alt+b"], "command": "insert_snippet", "args": {"contents": "${MD_BOLD_MARKER}$1${MD_BOLD_MARKER}"}, "context": - [ - { "key": "setting.auto_match_enabled", "operator": "equal", "operand": true }, - { "key": "selection_empty", "operator": "equal", "operand": true, "match_all": true }, - { "key": "following_text", "operator": "regex_contains", "operand": "^(?:\t| |\\)|]|\\}|$)", "match_all": true }, - { "key": "preceding_text", "operator": "not_regex_contains", "operand": "['a-zA-Z0-9_]$", "match_all": true }, - { "key": "eol_selector", "operator": "not_equal", "operand": "string.quoted.single", "match_all": true }, - { "key": "selector", "operator": "equal", "operand": "text.html.markdown", "match_all": true } - ] - }, - { "keys": ["alt+b"], "command": "insert_snippet", "args": {"contents": "${MD_BOLD_MARKER}${SELECTION/(^[\\*_]*|[\\*_]*$)//g}${MD_BOLD_MARKER}"}, "context": - [ - { "key": "setting.auto_match_enabled", "operator": "equal", "operand": true }, - { "key": "selection_empty", "operator": "equal", "operand": false, "match_all": true }, - { "key": "selector", "operator": "equal", "operand": "text.html.markdown", "match_all": true } - ] - }, - // italics on Alt + I - { "keys": ["alt+i"], "command": "run_macro_file", "args": {"file": "Packages/MarkdownEditing/macros/Transform Word - Italic.sublime-macro"}, "context": - [ - { "key": "selection_empty", "operator": "equal", "operand": true, "match_all": true }, - { "key": "selector", "operator": "equal", "operand": "text.html.markdown", "match_all": true } - ] - }, - { "keys": ["alt+i"], "command": "insert_snippet", "args": {"contents": "${MD_ITALIC_MARKER}$0${MD_ITALIC_MARKER}"}, "context": - [ - { "key": "setting.auto_match_enabled", "operator": "equal", "operand": true }, - { "key": "selection_empty", "operator": "equal", "operand": true, "match_all": true }, - { "key": "following_text", "operator": "regex_contains", "operand": "^(?:\t| |\\)|]|\\}|$)", "match_all": true }, - { "key": "preceding_text", "operator": "not_regex_contains", "operand": "['a-zA-Z0-9_]$", "match_all": true }, - { "key": "eol_selector", "operator": "not_equal", "operand": "string.quoted.single", "match_all": true }, - { "key": "selector", "operator": "equal", "operand": "text.html.markdown", "match_all": true } - ] - }, - { "keys": ["alt+i"], "command": "insert_snippet", "args": {"contents": "${MD_ITALIC_MARKER}${SELECTION/(^[\\*_]*|[\\*_]*$)//g}${MD_ITALIC_MARKER}"}, "context": - [ - { "key": "setting.auto_match_enabled", "operator": "equal", "operand": true }, - { "key": "selection_empty", "operator": "equal", "operand": false, "match_all": true }, - { "key": "selector", "operator": "equal", "operand": "text.html.markdown", "match_all": true } - ] - }, + // Fix smart expand selection + // see: https://github.com/sublimehq/sublime_text/issues/4125 + { "keys": ["ctrl+shift+a"], "command": "expand_selection", "args": {"to": "smart"}, "context": + [ + { "key": "selector", "operand": "text.html.markdown - text.html.markdown text.html - text.html.markdown text.xml - text.html.markdown meta.disable-markdown", "match_all": true } + ] + }, - // Unbold on Alt + B if already bold - { "keys": ["alt+b"], "command": "insert_snippet", "args": {"contents": "${SELECTION/(^[\\*_]{2}|[\\*_]{2}$)//g}"}, "context": - [ - { "key": "selection_empty", "operator": "equal", "operand": false, "match_all": true }, - { "key": "text", "operator": "regex_match", "operand": "^[*_]{2}.*[*_]{2}$", "match_all": true }, - { "key": "selector", "operator": "equal", "operand": "text.html.markdown", "match_all": true } - ] - }, - { "keys": ["alt+b"], "command": "run_macro_file", "args": {"file": "Packages/MarkdownEditing/macros/Transform Word - Unbold Unitalicize.sublime-macro"}, "context": - [ - { "key": "selection_empty", "operator": "equal", "operand": true, "match_all": true }, - { "key": "selector", "operator": "equal", "operand": "text.html.markdown markup.bold.markdown", "match_all": true } - ] - }, - { "keys": ["alt+b"], "command": "run_macro_file", "args": {"file": "Packages/MarkdownEditing/macros/Transform Word - Unbold Unitalicize.sublime-macro"}, "context": - [ - { "key": "selection_empty", "operator": "equal", "operand": true, "match_all": true }, - { "key": "preceding_text", "operator": "regex_contains", "operand": "\\b__+\\S+__+$", "match_all": true }, - { "key": "selector", "operator": "equal", "operand": "text.html.markdown", "match_all": true } - ] - }, + // + // Auto-Pairing Astersisks + // - // Unitalicize on Alt + I if already italic - { "keys": ["alt+i"], "command": "insert_snippet", "args": {"contents": "${SELECTION/(^[\\*_]|[\\*_]$)//g}"}, "context": - [ - { "key": "selection_empty", "operator": "equal", "operand": false, "match_all": true }, - { "key": "text", "operator": "regex_match", "operand": "^[*_].*[*_]$", "match_all": true }, - { "key": "selector", "operator": "equal", "operand": "text.html.markdown", "match_all": true } - ] - }, - { "keys": ["alt+i"], "command": "run_macro_file", "args": {"file": "Packages/MarkdownEditing/macros/Transform Word - Unbold Unitalicize.sublime-macro"}, "context": - [ - { "key": "selection_empty", "operator": "equal", "operand": true, "match_all": true }, - { "key": "selector", "operator": "equal", "operand": "text.html.markdown markup.italic.markdown", "match_all": true } - ] - }, - { "keys": ["alt+i"], "command": "run_macro_file", "args": {"file": "Packages/MarkdownEditing/macros/Transform Word - Unbold Unitalicize.sublime-macro"}, "context": - [ - { "key": "selection_empty", "operator": "equal", "operand": true, "match_all": true }, - { "key": "preceding_text", "operator": "regex_contains", "operand": "\\b_(?!_)\\S+_$", "match_all": true }, - { "key": "selector", "operator": "equal", "operand": "text.html.markdown", "match_all": true } - ] - }, + { "keys": ["*"], "command": "insert_snippet", "args": {"contents": "*$0*"}, "context": + [ + { "key": "selector", "operator": "equal", "operand": "text.html.markdown - meta.frontmatter - meta.disable-markdown - markup.raw - markup.kbd", "match_all": true }, + { "key": "setting.auto_match_enabled", "operator": "equal", "operand": true }, + { "key": "selection_empty", "operator": "equal", "operand": true, "match_all": true }, + { "key": "eol_selector", "operator": "not_equal", "operand": "string.quoted.single", "match_all": true }, + { "key": "preceding_text", "operator": "not_regex_contains", "operand": "['a-zA-Z0-9_*]$", "match_all": true }, + { "key": "following_text", "operator": "regex_contains", "operand": "^(?:\t| |\\)|]|\\}|$)", "match_all": true } + ] + }, + { "keys": ["*"], "command": "insert_snippet", "args": {"contents": "*${0:$SELECTION}*"}, "context": + [ + { "key": "selector", "operator": "equal", "operand": "text.html.markdown - meta.frontmatter - meta.disable-markdown - markup.raw - markup.kbd", "match_all": true }, + { "key": "setting.auto_match_enabled", "operator": "equal", "operand": true }, + { "key": "selection_empty", "operator": "equal", "operand": false, "match_all": true } + ] + }, + { "keys": ["*"], "command": "move", "args": {"by": "characters", "forward": true}, "context": + [ + { "key": "selector", "operator": "equal", "operand": "text.html.markdown - meta.frontmatter - meta.disable-markdown - markup.raw - markup.kbd", "match_all": true }, + { "key": "selection_empty", "operator": "equal", "operand": true, "match_all": true }, + { "key": "following_text", "operator": "regex_contains", "operand": "^\\*", "match_all": true } + ] + }, + { "keys": ["backspace"], "command": "run_macro_file", "args": {"file": "Packages/Default/Delete Left Right.sublime-macro"}, "context": + [ + { "key": "selector", "operator": "equal", "operand": "text.html.markdown - meta.frontmatter - meta.disable-markdown - markup.raw - markup.kbd", "match_all": true }, + { "key": "setting.auto_match_enabled", "operator": "equal", "operand": true }, + { "key": "selection_empty", "operator": "equal", "operand": true, "match_all": true }, + { "key": "preceding_text", "operator": "regex_contains", "operand": "\\*$", "match_all": true }, + { "key": "following_text", "operator": "regex_contains", "operand": "^\\*", "match_all": true } + ] + }, + { "keys": [" "], "command": "run_macro_file", "args": {"file": "Packages/MarkdownEditing/macros/Start List Item.sublime-macro"}, "context": + [ + { "key": "selector", "operator": "equal", "operand": "text.html.markdown - meta.frontmatter - meta.disable-markdown - markup.raw - markup.kbd", "match_all": true }, + { "key": "setting.auto_match_enabled", "operator": "equal", "operand": true }, + { "key": "selection_empty", "operator": "equal", "operand": true, "match_all": true }, + { "key": "preceding_text", "operator": "regex_contains", "operand": "\\*$", "match_all": true }, + { "key": "following_text", "operator": "regex_contains", "operand": "^\\*", "match_all": true } + ] + }, + { "keys": ["tab"], "command": "run_macro_file", "args": {"file": "Packages/MarkdownEditing/macros/Start List Item Tab.sublime-macro"}, "context": + [ + { "key": "selector", "operator": "equal", "operand": "text.html.markdown - meta.frontmatter - meta.disable-markdown - markup.raw - markup.kbd", "match_all": true }, + { "key": "setting.auto_match_enabled", "operator": "equal", "operand": true }, + { "key": "selection_empty", "operator": "equal", "operand": true, "match_all": true }, + { "key": "preceding_text", "operator": "regex_contains", "operand": "\\*$", "match_all": true }, + { "key": "following_text", "operator": "regex_contains", "operand": "^\\*", "match_all": true } + ] + }, - // Headers - { "keys": ["#"], "command": "insert_snippet", "args": {"contents": "#${0: ${SELECTION/(^ | $)//g} }#"}, "context": - [ - { "key": "selection_empty", "operator": "equal", "operand": false, "match_all": true }, - { "key": "selector", "operator": "equal", "operand": "text.html.markdown", "match_all": true }, - { "key": "preceding_text", "operator": "not_regex_contains", "operand": "#{6}", "match_all": true }, - { "key": "setting.mde.match_header_hashes", "operator": "equal", "operand": true }, - { "key": "selector", "operator": "not_equal", "operand": "markup.raw", "match_all": true } - ] - }, - { "keys": ["#"], "command": "insert_snippet", "args": {"contents": "#${0: ${SELECTION/(^ | $)//g}}"}, "context": - [ - { "key": "selection_empty", "operator": "equal", "operand": false, "match_all": true }, - { "key": "selector", "operator": "equal", "operand": "text.html.markdown", "match_all": true }, - { "key": "preceding_text", "operator": "not_regex_contains", "operand": "#{6}", "match_all": true }, - { "key": "setting.mde.match_header_hashes", "operator": "equal", "operand": false }, - { "key": "selector", "operator": "not_equal", "operand": "markup.raw", "match_all": true } - ] - }, - { "keys": ["#"], "command": "run_macro_file", "args": {"file": "Packages/MarkdownEditing/macros/Padded Headline.sublime-macro"}, "context": - [ - { "key": "selection_empty", "operator": "equal", "operand": false, "match_all": true }, - { "key": "selector", "operator": "equal", "operand": "text.html.markdown", "match_all": true }, - { "key": "preceding_text", "operator": "regex_contains", "operand": "#{6}", "match_all": true }, - { "key": "following_text", "operator": "regex_contains", "operand": "#+", "match_all": true }, - { "key": "setting.mde.match_header_hashes", "operator": "equal", "operand": true }, - { "key": "selector", "operator": "not_equal", "operand": "markup.raw", "match_all": true } - ] - }, - { "keys": ["#"], "command": "run_macro_file", "args": {"file": "Packages/MarkdownEditing/macros/Padded Headline.sublime-macro"}, "context": - [ - { "key": "selection_empty", "operator": "equal", "operand": false, "match_all": true }, - { "key": "selector", "operator": "equal", "operand": "text.html.markdown", "match_all": true }, - { "key": "preceding_text", "operator": "regex_contains", "operand": "#{6}", "match_all": true }, - { "key": "setting.mde.match_header_hashes", "operator": "equal", "operand": false }, - { "key": "selector", "operator": "not_equal", "operand": "markup.raw", "match_all": true } - ] - }, - { "keys": ["enter"], "command": "insert_snippet", "args": {"contents": " ${TM_CURRENT_LINE/(#+?)[^#].*$/$1\n/}"}, "context": - [ - { "key": "selector", "operator": "equal", "operand": "text.html.markdown", "match_all": true }, - { "key": "preceding_text", "operator": "regex_contains", "operand": "^#+\\s+[^#]", "match_all": true }, - { "key": "preceding_text", "operator": "not_regex_contains", "operand": "#+$", "match_all": true }, - { "key": "following_text", "operator": "regex_contains", "operand": "^\\s*$", "match_all": true }, - { "key": "setting.mde.match_header_hashes", "operator": "equal", "operand": true }, - { "key": "auto_complete_visible", "operator": "equal", "operand": false }, - { "key": "selector", "operator": "not_equal", "operand": "markup.raw", "match_all": true } - ] - }, - // Extend lists - { "keys": ["enter"], "command": "insert_snippet", "args": {"contents": "${TM_CURRENT_LINE/^(\\s*([*\\-+])(\\s+)).*/\n$2$3/}"}, "context": - [ - { "key": "selector", "operator": "equal", "operand": "text.html.markdown", "match_all": true }, - { "key": "preceding_text", "operator": "regex_contains", "operand": "^(\\s*([*\\-+])\\s+)\\S.*", "match_all": true }, - { "key": "auto_complete_visible", "operator": "equal", "operand": false }, - { "key": "selector", "operator": "not_equal", "operand": "markup.raw", "match_all": true } - ] - }, - // Extend lists with GFM tasks - { "keys": ["enter"], "command": "insert_snippet", "args": {"contents": "${TM_CURRENT_LINE/^(\\s*([*\\-+])(\\s+)\\[[ x]\\](\\s+)).*/\n$2$3[ ]$4/}"}, "context": - [ - { "key": "selector", "operator": "equal", "operand": "text.html.markdown", "match_all": true }, - { "key": "preceding_text", "operator": "regex_contains", "operand": "^(\\s*([*\\-+])\\s+)\\[[ x]\\]\\s+\\S.*", "match_all": true }, - { "key": "auto_complete_visible", "operator": "equal", "operand": false }, - { "key": "selector", "operator": "not_equal", "operand": "markup.raw", "match_all": true } - ] - }, - // Extend Numbered Lists - { "keys": ["enter"], "command": "number_list", "context": - [ - { "key": "selector", "operator": "equal", "operand": "text.html.markdown", "match_all": true }, - { "key": "preceding_text", "operator": "regex_contains", "operand": "^(\\s*(\\d+\\.)\\s+)\\S.*", "match_all": true }, - { "key": "auto_complete_visible", "operator": "equal", "operand": false }, - { "key": "selector", "operator": "not_equal", "operand": "markup.raw", "match_all": true } - ] - }, - // Extend Numbered Reference - { "keys": ["enter"], "command": "number_list_reference", "context": - [ - { "key": "selector", "operator": "equal", "operand": "text.html.markdown", "match_all": true }, - { "key": "preceding_text", "operator": "regex_contains", "operand": "^(\\s*\\[(\\d+)\\]:\\s*)\\S.*", "match_all": true }, - { "key": "auto_complete_visible", "operator": "equal", "operand": false }, - { "key": "selector", "operator": "not_equal", "operand": "markup.raw", "match_all": true } - ] - }, - // Remove empty list item - { "keys": ["enter"], "command": "run_macro_file", "args": {"file": "Packages/MarkdownEditing/macros/Remove Empty List Item.sublime-macro"}, "context": - [ - { "key": "selector", "operator": "equal", "operand": "text.html.markdown", "match_all": true }, - { "key": "preceding_text", "operator": "regex_contains", "operand": "^(\\s*(\\[\\d+\\]:|[*\\-+]|\\d+\\.)\\s+)$", "match_all": true }, - { "key": "following_text", "operator": "regex_contains", "operand": "^\\s*$", "match_all": true }, - { "key": "auto_complete_visible", "operator": "equal", "operand": false }, - { "key": "selector", "operator": "not_equal", "operand": "markup.raw", "match_all": true } - ] - }, - // Extend blockquote - { "keys": ["enter"], "command": "insert_snippet", "args": {"contents": "${TM_CURRENT_LINE/^(\\s*((>+\\s+)+([*\\-+]\\s+)?)).*/\n$2/}"}, "context": - [ - { "key": "selector", "operator": "equal", "operand": "text.html.markdown", "match_all": true }, - { "key": "preceding_text", "operator": "regex_contains", "operand": "^\\s*>+\\s+", "match_all": true }, - { "key": "auto_complete_visible", "operator": "equal", "operand": false } - ] - }, - // Convert to blockquote - { "keys": [">"], "command": "run_macro_file", "args": {"file": "Packages/MarkdownEditing/macros/Convert to Blockquote.sublime-macro"}, "context": - [ - { "key": "selection_empty", "operator": "equal", "operand": false, "match_all": true }, - { "key": "selector", "operator": "equal", "operand": "text.html.markdown", "match_all": true }, - { "key": "selector", "operator": "not_equal", "operand": "markup.raw", "match_all": true } - ] - }, - { "keys": ["tab"], "command": "complete_underlined_header", "context": - [ - { "key": "selector", "operator": "equal", "operand": "text.html.markdown", "match_all": true }, - { "key": "selection_empty", "operator": "equal", "operand": true, "match_all": true }, - { "key": "auto_complete_visible", "operator": "equal", "operand": false, "match_all": true }, - { "key": "preceding_text", "operator": "regex_contains", "operand": "^\\-+$|^\\=+$", "match_all": true }, - { "key": "selector", "operator": "not_equal", "operand": "markup.raw", "match_all": true } - ] - }, - // Surround with <> on URLs, regex copied from https://mathiasbynens.be/demo/url-regex, @diegoperini (502 chars) - { "keys": ["<"], "command": "insert_snippet", "args": {"contents": "<${0:$SELECTION}>"}, "context": - [ - { "key": "setting.auto_match_enabled", "operator": "equal", "operand": true }, - { "key": "selection_empty", "operator": "equal", "operand": false, "match_all": true }, - { "key": "selector", "operator": "equal", "operand": "text.html.markdown", "match_all": true }, - { "key": "text", "operator": "regex_match", "operand": "(?:(?:https?|ftp)://)(?:\\S+(?::\\S*)?@)?(?:(?!10(?:\\.\\d{1,3}){3})(?!127(?:\\.\\d{1,3}){3})(?!169\\.254(?:\\.\\d{1,3}){2})(?!192\\.168(?:\\.\\d{1,3}){2})(?!172\\.(?:1[6-9]|2\\d|3[0-1])(?:\\.\\d{1,3}){2})(?:[1-9]\\d?|1\\d\\d|2[01]\\d|22[0-3])(?:\\.(?:1?\\d{1,2}|2[0-4]\\d|25[0-5])){2}(?:\\.(?:[1-9]\\d?|1\\d\\d|2[0-4]\\d|25[0-4]))|(?:(?:[a-z\\x{00a1}-\\x{ffff}0-9]+-?)*[a-z\\x{00a1}-\\x{ffff}0-9]+)(?:\\.(?:[a-z\\x{00a1}-\\x{ffff}0-9]+-?)*[a-z\\x{00a1}-\\x{ffff}0-9]+)*(?:\\.(?:[a-z\\x{00a1}-\\x{ffff}]{2,})))(?::\\d{2,5})?(?:/[^\\s]*)?", "match_all": true } - ] - }, + // + // Auto-Pairing Underscore + // - // inline image insertion - { "keys": ["super+shift+k"], "command": "reference_new_inline_image", "context": - [ - { "key": "setting.mde.keymap_disable.reference_new_inline_image", "operator": "not_equal", "operand": true }, - { "key": "selector", "operator": "equal", "operand": "text.html.markdown", "match_all": true } - ] - }, - // modify [] pairing so that selection is removed after pairing, ready for [] or () - { "keys": ["["], "command": "insert_snippet", "args": {"contents": "[$SELECTION]$0"}, "context": - [ - { "key": "setting.auto_match_enabled", "operator": "equal", "operand": true }, - { "key": "selection_empty", "operator": "equal", "operand": false, "match_all": true }, - { "key": "selector", "operator": "equal", "operand": "text.html.markdown", "match_all": true } - ] - }, - // run paste as link command on selected text - { "keys": ["ctrl+alt+v"], "command": "reference_new_inline_link", "context": - [ - { "key": "setting.mde.keymap_disable.reference_new_inline_link", "operator": "not_equal", "operand": true }, - { "key": "selector", "operator": "equal", "operand": "text.html.markdown", "match_all": true } - ] - }, - { "keys": ["ctrl+alt+r"], "command": "reference_new_reference", "context": - [ - { "key": "setting.mde.keymap_disable.reference_new_reference", "operator": "not_equal", "operand": true }, - { "key": "selector", "operator": "equal", "operand": "text.html.markdown", "match_all": true } - ] - }, - { "keys": ["ctrl+alt+g"], "command": "reference_jump", "context": - [ - { "key": "setting.mde.keymap_disable.reference_jump", "operator": "not_equal", "operand": true }, - { "key": "selector", "operator": "equal", "operand": "text.html.markdown", "match_all": true } - ] - }, - // Set Headers Levels With Shortcuts - { "keys": ["ctrl+1"], "command": "insert_snippet", "args": {"contents": "# $0"}, "context": - [ - { "key": "setting.auto_match_enabled", "operator": "equal", "operand": true }, - { "key": "selection_empty", "operator": "equal", "operand": true, "match_all": true }, - { "key": "following_text", "operator": "regex_contains", "operand": "^(?:\t| |\\)|]|\\}|$)", "match_all": true }, - { "key": "preceding_text", "operator": "not_regex_contains", "operand": "['a-zA-Z0-9_]$", "match_all": true }, - { "key": "eol_selector", "operator": "not_equal", "operand": "string.quoted.single", "match_all": true }, - { "key": "selector", "operator": "equal", "operand": "text.html.markdown", "match_all": true } - ] - }, - { "keys": ["ctrl+1"], "command": "insert_snippet", "args": {"contents": "#${0: ${SELECTION/(^( +)?(#+)?\\s*|\\s*(#+)?( +)?$)//g}}$1"}, "context": - [ - { "key": "setting.auto_match_enabled", "operator": "equal", "operand": true }, - { "key": "setting.mde.match_header_hashes", "operator": "equal", "operand": false }, - { "key": "selection_empty", "operator": "equal", "operand": false, "match_all": true }, - { "key": "selector", "operator": "equal", "operand": "text.html.markdown", "match_all": true } - ] - }, - { "keys": ["ctrl+1"], "command": "insert_snippet", "args": {"contents": "#${0: ${SELECTION/(^( +)?(#+)?\\s*|\\s*(#+)?( +)?$)//g} }#$1"}, "context": - [ - { "key": "setting.auto_match_enabled", "operator": "equal", "operand": true }, - { "key": "setting.mde.match_header_hashes", "operator": "equal", "operand": true }, - { "key": "selection_empty", "operator": "equal", "operand": false, "match_all": true }, - { "key": "selector", "operator": "equal", "operand": "text.html.markdown", "match_all": true } - ] - }, - { "keys": ["ctrl+2"], "command": "insert_snippet", "args": {"contents": "## $0"}, "context": - [ - { "key": "setting.auto_match_enabled", "operator": "equal", "operand": true }, - { "key": "selection_empty", "operator": "equal", "operand": true, "match_all": true }, - { "key": "following_text", "operator": "regex_contains", "operand": "^(?:\t| |\\)|]|\\}|$)", "match_all": true }, - { "key": "preceding_text", "operator": "not_regex_contains", "operand": "['a-zA-Z0-9_]$", "match_all": true }, - { "key": "eol_selector", "operator": "not_equal", "operand": "string.quoted.single", "match_all": true }, - { "key": "selector", "operator": "equal", "operand": "text.html.markdown", "match_all": true } - ] - }, - { "keys": ["ctrl+2"], "command": "insert_snippet", "args": {"contents": "##${0: ${SELECTION/(^( +)?(#+)?\\s*|\\s*(#+)?( +)?$)//g}}$1"}, "context": - [ - { "key": "setting.auto_match_enabled", "operator": "equal", "operand": true }, - { "key": "setting.mde.match_header_hashes", "operator": "equal", "operand": false }, - { "key": "selection_empty", "operator": "equal", "operand": false, "match_all": true }, - { "key": "selector", "operator": "equal", "operand": "text.html.markdown", "match_all": true } - ] - }, - { "keys": ["ctrl+2"], "command": "insert_snippet", "args": {"contents": "##${0: ${SELECTION/(^( +)?(#+)?\\s*|\\s*(#+)?( +)?$)//g} }##$1"}, "context": - [ - { "key": "setting.auto_match_enabled", "operator": "equal", "operand": true }, - { "key": "setting.mde.match_header_hashes", "operator": "equal", "operand": true }, - { "key": "selection_empty", "operator": "equal", "operand": false, "match_all": true }, - { "key": "selector", "operator": "equal", "operand": "text.html.markdown", "match_all": true } - ] - }, - { "keys": ["ctrl+3"], "command": "insert_snippet", "args": {"contents": "### $0"}, "context": - [ - { "key": "setting.auto_match_enabled", "operator": "equal", "operand": true }, - { "key": "selection_empty", "operator": "equal", "operand": true, "match_all": true }, - { "key": "following_text", "operator": "regex_contains", "operand": "^(?:\t| |\\)|]|\\}|$)", "match_all": true }, - { "key": "preceding_text", "operator": "not_regex_contains", "operand": "['a-zA-Z0-9_]$", "match_all": true }, - { "key": "eol_selector", "operator": "not_equal", "operand": "string.quoted.single", "match_all": true }, - { "key": "selector", "operator": "equal", "operand": "text.html.markdown", "match_all": true } - ] - }, - { "keys": ["ctrl+3"], "command": "insert_snippet", "args": {"contents": "###${0: ${SELECTION/(^( +)?(#+)?\\s*|\\s*(#+)?( +)?$)//g}}$1"}, "context": - [ - { "key": "setting.auto_match_enabled", "operator": "equal", "operand": true }, - { "key": "setting.mde.match_header_hashes", "operator": "equal", "operand": false }, - { "key": "selection_empty", "operator": "equal", "operand": false, "match_all": true }, - { "key": "selector", "operator": "equal", "operand": "text.html.markdown", "match_all": true } - ] - }, - { "keys": ["ctrl+3"], "command": "insert_snippet", "args": {"contents": "###${0: ${SELECTION/(^( +)?(#+)?\\s*|\\s*(#+)?( +)?$)//g} }###$1"}, "context": - [ - { "key": "setting.auto_match_enabled", "operator": "equal", "operand": true }, - { "key": "setting.mde.match_header_hashes", "operator": "equal", "operand": true }, - { "key": "selection_empty", "operator": "equal", "operand": false, "match_all": true }, - { "key": "selector", "operator": "equal", "operand": "text.html.markdown", "match_all": true } - ] - }, - { "keys": ["ctrl+4"], "command": "insert_snippet", "args": {"contents": "#### $0"}, "context": - [ - { "key": "setting.auto_match_enabled", "operator": "equal", "operand": true }, - { "key": "selection_empty", "operator": "equal", "operand": true, "match_all": true }, - { "key": "following_text", "operator": "regex_contains", "operand": "^(?:\t| |\\)|]|\\}|$)", "match_all": true }, - { "key": "preceding_text", "operator": "not_regex_contains", "operand": "['a-zA-Z0-9_]$", "match_all": true }, - { "key": "eol_selector", "operator": "not_equal", "operand": "string.quoted.single", "match_all": true }, - { "key": "selector", "operator": "equal", "operand": "text.html.markdown", "match_all": true } - ] - }, - { "keys": ["ctrl+4"], "command": "insert_snippet", "args": {"contents": "####${0: ${SELECTION/(^( +)?(#+)?\\s*|\\s*(#+)?( +)?$)//g}}$1"}, "context": - [ - { "key": "setting.auto_match_enabled", "operator": "equal", "operand": true }, - { "key": "setting.mde.match_header_hashes", "operator": "equal", "operand": false }, - { "key": "selection_empty", "operator": "equal", "operand": false, "match_all": true }, - { "key": "selector", "operator": "equal", "operand": "text.html.markdown", "match_all": true } - ] - }, - { "keys": ["ctrl+4"], "command": "insert_snippet", "args": {"contents": "####${0: ${SELECTION/(^( +)?(#+)?\\s*|\\s*(#+)?( +)?$)//g} }####$1"}, "context": - [ - { "key": "setting.auto_match_enabled", "operator": "equal", "operand": true }, - { "key": "setting.mde.match_header_hashes", "operator": "equal", "operand": true }, - { "key": "selection_empty", "operator": "equal", "operand": false, "match_all": true }, - { "key": "selector", "operator": "equal", "operand": "text.html.markdown", "match_all": true } - ] - }, - { "keys": ["ctrl+5"], "command": "insert_snippet", "args": {"contents": "##### $0"}, "context": - [ - { "key": "setting.auto_match_enabled", "operator": "equal", "operand": true }, - { "key": "selection_empty", "operator": "equal", "operand": true, "match_all": true }, - { "key": "following_text", "operator": "regex_contains", "operand": "^(?:\t| |\\)|]|\\}|$)", "match_all": true }, - { "key": "preceding_text", "operator": "not_regex_contains", "operand": "['a-zA-Z0-9_]$", "match_all": true }, - { "key": "eol_selector", "operator": "not_equal", "operand": "string.quoted.single", "match_all": true }, - { "key": "selector", "operator": "equal", "operand": "text.html.markdown", "match_all": true } - ] - }, - { "keys": ["ctrl+5"], "command": "insert_snippet", "args": {"contents": "#####${0: ${SELECTION/(^( +)?(#+)?\\s*|\\s*(#+)?( +)?$)//g}}$1"}, "context": - [ - { "key": "setting.auto_match_enabled", "operator": "equal", "operand": true }, - { "key": "setting.mde.match_header_hashes", "operator": "equal", "operand": false }, - { "key": "selection_empty", "operator": "equal", "operand": false, "match_all": true }, - { "key": "selector", "operator": "equal", "operand": "text.html.markdown", "match_all": true } - ] - }, - { "keys": ["ctrl+5"], "command": "insert_snippet", "args": {"contents": "#####${0: ${SELECTION/(^( +)?(#+)?\\s*|\\s*(#+)?( +)?$)//g} }#####$1"}, "context": - [ - { "key": "setting.auto_match_enabled", "operator": "equal", "operand": true }, - { "key": "setting.mde.match_header_hashes", "operator": "equal", "operand": true }, - { "key": "selection_empty", "operator": "equal", "operand": false, "match_all": true }, - { "key": "selector", "operator": "equal", "operand": "text.html.markdown", "match_all": true } - ] - }, - { "keys": ["ctrl+6"], "command": "insert_snippet", "args": {"contents": "###### $0"}, "context": - [ - { "key": "setting.auto_match_enabled", "operator": "equal", "operand": true }, - { "key": "selection_empty", "operator": "equal", "operand": true, "match_all": true }, - { "key": "following_text", "operator": "regex_contains", "operand": "^(?:\t| |\\)|]|\\}|$)", "match_all": true }, - { "key": "preceding_text", "operator": "not_regex_contains", "operand": "['a-zA-Z0-9_]$", "match_all": true }, - { "key": "eol_selector", "operator": "not_equal", "operand": "string.quoted.single", "match_all": true }, - { "key": "selector", "operator": "equal", "operand": "text.html.markdown", "match_all": true } - ] - }, - { "keys": ["ctrl+6"], "command": "insert_snippet", "args": {"contents": "######${0: ${SELECTION/(^( +)?(#+)?\\s*|\\s*(#+)?( +)?$)//g}}$1"}, "context": - [ - { "key": "setting.auto_match_enabled", "operator": "equal", "operand": true }, - { "key": "setting.mde.match_header_hashes", "operator": "equal", "operand": false }, - { "key": "selection_empty", "operator": "equal", "operand": false, "match_all": true }, - { "key": "selector", "operator": "equal", "operand": "text.html.markdown", "match_all": true } - ] - }, - { "keys": ["ctrl+6"], "command": "insert_snippet", "args": {"contents": "######${0: ${SELECTION/(^( +)?(#+)?\\s*|\\s*(#+)?( +)?$)//g} }######$1"}, "context": - [ - { "key": "setting.auto_match_enabled", "operator": "equal", "operand": true }, - { "key": "setting.mde.match_header_hashes", "operator": "equal", "operand": true }, - { "key": "selection_empty", "operator": "equal", "operand": false, "match_all": true }, - { "key": "selector", "operator": "equal", "operand": "text.html.markdown", "match_all": true } - ] - }, - { "keys": ["alt+shift+6"], "command": "reference_new_footnote", "context": - [ - { "key": "setting.mde.keymap_disable.reference_new_footnote", "operator": "not_equal", "operand": true }, - { "key": "selector", "operator": "equal", "operand": "text.html.markdown", "match_all": true } - ] - }, - { "keys": ["ctrl+shift+."], "command": "indent_quote", "context": - [ - { "key": "selector", "operator": "equal", "operand": "text.html.markdown", "match_all": true } - ] - }, - { "keys": ["ctrl+shift+,"], "command": "deindent_quote", "context": - [ - { "key": "selector", "operator": "equal", "operand": "text.html.markdown", "match_all": true }, - { "key": "preceding_text", "operator": "regex_contains", "operand": "(> )+", "match_all": true } - ] - }, - { "keys": ["shift+tab"], "command": "fold_section", "context": - [ - { "key": "setting.mde.keymap_disable.fold_section", "operator": "not_equal", "operand": true }, - { "key": "selection_empty", "operator": "equal", "operand": true, "match_all": true }, - { "key": "preceding_text", "operator": "not_regex_match", "operand": "^\\s+", "match_all": true }, - { "key": "following_text", "operator": "not_regex_match", "operand": "^$", "match_all": true }, - { "key": "selector", "operator": "equal", "operand": "text.html.markdown", "match_all": true } - ] - }, - { "keys": ["shift+tab"], "command": "fold_section", "context": - [ - { "key": "setting.mde.keymap_disable.fold_section", "operator": "not_equal", "operand": true }, - { "key": "selection_empty", "operator": "equal", "operand": true, "match_all": true }, - { "key": "preceding_text", "operator": "not_regex_match", "operand": "^\\s+", "match_all": true }, - { "key": "selector", "operator": "not_equal", "operand": "markup.list", "match_all": true }, - { "key": "selector", "operator": "equal", "operand": "text.html.markdown", "match_all": true } - ] - }, - { "keys": ["shift+tab"], "command": "fold_section", "context": - [ - { "key": "setting.mde.keymap_disable.fold_section", "operator": "not_equal", "operand": true }, - { "key": "selection_empty", "operator": "equal", "operand": false, "match_all": true }, - { "key": "text", "operator": "regex_contains", "operand": "^(#{1,6}(?!#))|^(-{3,}|={3,})$"}, - { "key": "selector", "operator": "equal", "operand": "text.html.markdown", "match_all": true } - ] - }, - { "keys": ["ctrl+shift+tab"], "command": "show_fold_all_sections", "context": - [ - { "key": "setting.mde.keymap_disable.show_fold_all_sections", "operator": "not_equal", "operand": true }, - { "key": "selector", "operator": "equal", "operand": "text.html.markdown", "match_all": true } - ] - }, - { "keys": ["ctrl+shift+alt+pageup"], "command": "goto_previous_heading", "args": {"same_level": true}, "context": - [ - { "key": "setting.mde.keymap_disable.goto_previous_heading", "operator": "not_equal", "operand": true }, - { "key": "selector", "operator": "equal", "operand": "text.html.markdown", "match_all": true } - ] - }, - { "keys": ["ctrl+shift+alt+pagedown"], "command": "goto_next_heading", "args": {"same_level": true}, "context": - [ - { "key": "setting.mde.keymap_disable.goto_next_heading", "operator": "not_equal", "operand": true }, - { "key": "selector", "operator": "equal", "operand": "text.html.markdown", "match_all": true } - ] - }, - { "keys": ["ctrl+shift+pageup"], "command": "goto_previous_heading", "args": {"same_level": false}, "context": - [ - { "key": "setting.mde.keymap_disable.goto_previous_heading", "operator": "not_equal", "operand": true }, - { "key": "selector", "operator": "equal", "operand": "text.html.markdown", "match_all": true } - ] - }, - { "keys": ["ctrl+shift+pagedown"], "command": "goto_next_heading", "args": {"same_level": false}, "context": - [ - { "key": "setting.mde.keymap_disable.goto_next_heading", "operator": "not_equal", "operand": true }, - { "key": "selector", "operator": "equal", "operand": "text.html.markdown", "match_all": true } - ] - }, - {"keys": ["ctrl+alt+h"], "command": "open_home_page", "context": - [ - { "key": "setting.mde.keymap_disable.open_home_page", "operator": "not_equal", "operand": true }, - { "key": "selector", "operator": "equal", "operand": "text.html.markdown", "match_all": true } - ] - }, - {"keys": ["ctrl+alt+d"], "command": "open_page", "context": - [ - { "key": "setting.mde.keymap_disable.open_page", "operator": "not_equal", "operand": true }, - { "key": "selector", "operator": "equal", "operand": "meta.link.wiki.markdown", "match_all": true } - ] - }, - {"keys": ["ctrl+alt+d"], "command": "make_page_reference", "context": - [ - { "key": "setting.mde.keymap_disable.make_page_reference", "operator": "not_equal", "operand": true }, - { "key": "selector", "operator": "equal", "operand": "text.html.markdown", "match_all": true }, - { "key": "selector", "operator": "not_equal", "operand": "meta.link.wiki.markdown", "match_all": true }, - { "key": "selector", "operator": "not_equal", "operand": "markup.underline.link.markdown", "match_all": true } - ] - }, - {"keys": ["ctrl+alt+x"], "command": "list_back_links", "context": - [ - { "key": "setting.mde.keymap_disable.list_back_links", "operator": "not_equal", "operand": true }, - { "key": "selector", "operator": "equal", "operand": "text.html.markdown", "match_all": true } - ] - }, - {"keys": ["ctrl+alt+j"], "command": "open_journal", "context": - [ - { "key": "setting.mde.keymap_disable.open_journal", "operator": "not_equal", "operand": true }, - { "key": "selector", "operator": "equal", "operand": "text.html.markdown", "match_all": true } - ] - } + { "keys": ["_"], "command": "insert_snippet", "args": {"contents": "_$0_"}, "context": + [ + { "key": "selector", "operator": "equal", "operand": "text.html.markdown - meta.frontmatter - meta.disable-markdown - markup.raw - markup.kbd", "match_all": true }, + { "key": "setting.auto_match_enabled", "operator": "equal", "operand": true }, + { "key": "selection_empty", "operator": "equal", "operand": true, "match_all": true }, + { "key": "eol_selector", "operator": "not_equal", "operand": "string.quoted.single", "match_all": true }, + { "key": "preceding_text", "operator": "not_regex_contains", "operand": "['a-zA-Z0-9_]$", "match_all": true }, + { "key": "following_text", "operator": "regex_contains", "operand": "^(?:\t| |\\)|]|\\}|$)", "match_all": true } + ] + }, + { "keys": ["_"], "command": "insert_snippet", "args": {"contents": "_${0:$SELECTION}_"}, "context": + [ + { "key": "selector", "operator": "equal", "operand": "text.html.markdown - meta.frontmatter - meta.disable-markdown - markup.raw - markup.kbd", "match_all": true }, + { "key": "setting.auto_match_enabled", "operator": "equal", "operand": true }, + { "key": "selection_empty", "operator": "equal", "operand": false, "match_all": true } + ] + }, + { "keys": ["_"], "command": "move", "args": {"by": "characters", "forward": true}, "context": + [ + { "key": "selector", "operator": "equal", "operand": "text.html.markdown - meta.frontmatter - meta.disable-markdown - markup.raw - markup.kbd", "match_all": true }, + { "key": "selection_empty", "operator": "equal", "operand": true, "match_all": true }, + { "key": "following_text", "operator": "regex_contains", "operand": "^_", "match_all": true } + ] + }, + { "keys": ["backspace"], "command": "run_macro_file", "args": {"file": "Packages/Default/Delete Left Right.sublime-macro"}, "context": + [ + { "key": "selector", "operator": "equal", "operand": "text.html.markdown - meta.frontmatter - meta.disable-markdown - markup.raw - markup.kbd", "match_all": true }, + { "key": "setting.auto_match_enabled", "operator": "equal", "operand": true }, + { "key": "selection_empty", "operator": "equal", "operand": true, "match_all": true }, + { "key": "preceding_text", "operator": "regex_contains", "operand": "_$", "match_all": true }, + { "key": "following_text", "operator": "regex_contains", "operand": "^_", "match_all": true } + ] + }, + { "keys": [" "], "command": "run_macro_file", "args": {"file": "Packages/MarkdownEditing/macros/Start List Item.sublime-macro"}, "context": + [ + { "key": "selector", "operator": "equal", "operand": "text.html.markdown - meta.frontmatter - meta.disable-markdown - markup.raw - markup.kbd", "match_all": true }, + { "key": "setting.auto_match_enabled", "operator": "equal", "operand": true }, + { "key": "selection_empty", "operator": "equal", "operand": true, "match_all": true }, + { "key": "preceding_text", "operator": "regex_contains", "operand": "\\_$", "match_all": true }, + { "key": "following_text", "operator": "regex_contains", "operand": "^\\_", "match_all": true } + ] + }, + { "keys": ["tab"], "command": "run_macro_file", "args": {"file": "Packages/MarkdownEditing/macros/Start List Item Tab.sublime-macro"}, "context": + [ + { "key": "selector", "operator": "equal", "operand": "text.html.markdown - meta.frontmatter - meta.disable-markdown - markup.raw - markup.kbd", "match_all": true }, + { "key": "setting.auto_match_enabled", "operator": "equal", "operand": true }, + { "key": "selection_empty", "operator": "equal", "operand": true, "match_all": true }, + { "key": "preceding_text", "operator": "regex_contains", "operand": "\\_$", "match_all": true }, + { "key": "following_text", "operator": "regex_contains", "operand": "^\\_", "match_all": true } + ] + }, + + // + // Auto-Pairing Inline Code + // + + { "keys": ["`"], "command": "insert_snippet", "args": {"contents": "`$0`"}, "context": + [ + { "key": "selector", "operator": "equal", "operand": "text.html.markdown - meta.frontmatter - meta.disable-markdown - markup.raw - markup.kbd", "match_all": true }, + { "key": "setting.auto_match_enabled", "operator": "equal", "operand": true }, + { "key": "selection_empty", "operator": "equal", "operand": true, "match_all": true }, + { "key": "preceding_text", "operator": "not_regex_contains", "operand": "[\\w`]$", "match_all": true }, + { "key": "following_text", "operator": "regex_contains", "operand": "^(?:\t| |\\)|]|\\}|\\.|,|$)", "match_all": true } + ] + }, + { "keys": ["`"], "command": "insert_snippet", "args": {"contents": "`${0:$SELECTION}`"}, "context": + [ + { "key": "selector", "operator": "equal", "operand": "text.html.markdown - meta.frontmatter - meta.disable-markdown - markup.raw - markup.kbd", "match_all": true }, + { "key": "setting.auto_match_enabled", "operator": "equal", "operand": true }, + { "key": "selection_empty", "operator": "equal", "operand": false, "match_all": true } + ] + }, + { "keys": ["`"], "command": "move", "args": {"by": "characters", "forward": true}, "context": + [ + { "key": "selector", "operator": "equal", "operand": "text.html.markdown - meta.frontmatter - meta.disable-markdown - markup.raw - markup.kbd", "match_all": true }, + { "key": "selection_empty", "operator": "equal", "operand": true, "match_all": true }, + { "key": "following_text", "operator": "regex_contains", "operand": "^`", "match_all": true } + ] + }, + { "keys": ["backspace"], "command": "run_macro_file", "args": {"file": "Packages/Default/Delete Left Right.sublime-macro"}, "context": + [ + { "key": "selector", "operator": "equal", "operand": "text.html.markdown - meta.frontmatter - meta.disable-markdown - markup.raw - markup.kbd", "match_all": true }, + { "key": "setting.auto_match_enabled", "operator": "equal", "operand": true }, + { "key": "selection_empty", "operator": "equal", "operand": true, "match_all": true }, + { "key": "preceding_text", "operator": "regex_contains", "operand": "`$", "match_all": true }, + { "key": "following_text", "operator": "regex_contains", "operand": "^`", "match_all": true } + ] + }, + + // + // Auto-Pairing Strike Through + // + + { "keys": ["~"], "command": "insert_snippet", "args": {"contents": "~~${0:$SELECTION}~~"}, "context": + [ + { "key": "selector", "operator": "equal", "operand": "text.html.markdown - meta.frontmatter - meta.disable-markdown - markup.raw - markup.kbd", "match_all": true }, + { "key": "setting.auto_match_enabled", "operator": "equal", "operand": true }, + { "key": "selection_empty", "operator": "equal", "operand": false, "match_all": true } + ] + }, + { "keys": ["backspace"], "command": "run_macro_file", "args": {"file": "Packages/MarkdownEditing/macros/Delete Left Right 2.sublime-macro"}, "context": + [ + { "key": "selector", "operator": "equal", "operand": "text.html.markdown - meta.frontmatter - meta.disable-markdown - markup.raw - markup.kbd", "match_all": true }, + { "key": "setting.auto_match_enabled", "operator": "equal", "operand": true }, + { "key": "selection_empty", "operator": "equal", "operand": true, "match_all": true }, + { "key": "preceding_text", "operator": "regex_contains", "operand": "~~$", "match_all": true }, + { "key": "following_text", "operator": "regex_contains", "operand": "^~~", "match_all": true } + ] + }, + + // + // Text Formatting Bold + // + + // auto-pair if not within a word + { "keys": ["alt+b"], "command": "insert_snippet", "args": {"contents": "**$0**"}, "context": + [ + { "key": "selector", "operator": "equal", "operand": "text.html.markdown - meta.frontmatter - meta.disable-markdown - markup.raw - markup.kbd - markup.bold - markup.bold_italic", "match_all": true }, + { "key": "setting.mde.bold_marker_asterisk", "operator": "equal", "operand": true }, + { "key": "selection_empty", "operator": "equal", "operand": true, "match_all": true }, + { "key": "eol_selector", "operator": "not_equal", "operand": "string.quoted.single", "match_all": true }, + { "key": "preceding_text", "operator": "not_regex_contains", "operand": "['a-zA-Z0-9_*]$", "match_all": true }, + { "key": "following_text", "operator": "regex_contains", "operand": "^(?:\t| |\\)|]|\\}|$)", "match_all": true } + ] + }, + { "keys": ["alt+b"], "command": "insert_snippet", "args": {"contents": "__$0__"}, "context": + [ + { "key": "selector", "operator": "equal", "operand": "text.html.markdown - meta.frontmatter - meta.disable-markdown - markup.raw - markup.kbd - markup.bold - markup.bold_italic", "match_all": true }, + { "key": "setting.mde.bold_marker_asterisk", "operator": "equal", "operand": false }, + { "key": "selection_empty", "operator": "equal", "operand": true, "match_all": true }, + { "key": "eol_selector", "operator": "not_equal", "operand": "string.quoted.single", "match_all": true }, + { "key": "preceding_text", "operator": "not_regex_contains", "operand": "['a-zA-Z0-9_*]$", "match_all": true }, + { "key": "following_text", "operator": "regex_contains", "operand": "^(?:\t| |\\)|]|\\}|$)", "match_all": true } + ] + }, + // Transform a word to bold if caret is at the beginning, in the middle of or at the end of a word + { "keys": ["alt+b"], "command": "run_macro_file", "args": {"file": "Packages/MarkdownEditing/macros/Transform Word - Bold (Asterisk).sublime-macro"}, "context": + [ + { "key": "selector", "operator": "equal", "operand": "text.html.markdown - meta.frontmatter - meta.disable-markdown - markup.raw - markup.kbd - markup.bold - markup.bold_italic", "match_all": true }, + { "key": "setting.mde.bold_marker_asterisk", "operator": "equal", "operand": true }, + { "key": "selection_empty", "operator": "equal", "operand": true, "match_all": true }, + { "key": "preceding_text", "operator": "regex_contains", "operand": "\\w$", "match_all": true } + ] + }, + { "keys": ["alt+b"], "command": "run_macro_file", "args": {"file": "Packages/MarkdownEditing/macros/Transform Word - Bold (Asterisk).sublime-macro"}, "context": + [ + { "key": "selector", "operator": "equal", "operand": "text.html.markdown - meta.frontmatter - meta.disable-markdown - markup.raw - markup.kbd - markup.bold - markup.bold_italic", "match_all": true }, + { "key": "setting.mde.bold_marker_asterisk", "operator": "equal", "operand": true }, + { "key": "selection_empty", "operator": "equal", "operand": true, "match_all": true }, + { "key": "following_text", "operator": "regex_contains", "operand": "^\\w", "match_all": true } + ] + }, + { "keys": ["alt+b"], "command": "run_macro_file", "args": {"file": "Packages/MarkdownEditing/macros/Transform Word - Bold (Underscore).sublime-macro"}, "context": + [ + { "key": "selector", "operator": "equal", "operand": "text.html.markdown - meta.frontmatter - meta.disable-markdown - markup.raw - markup.kbd - markup.bold - markup.bold_italic", "match_all": true }, + { "key": "setting.mde.bold_marker_asterisk", "operator": "equal", "operand": false }, + { "key": "selection_empty", "operator": "equal", "operand": true, "match_all": true }, + { "key": "preceding_text", "operator": "regex_contains", "operand": "\\w$", "match_all": true } + ] + }, + { "keys": ["alt+b"], "command": "run_macro_file", "args": {"file": "Packages/MarkdownEditing/macros/Transform Word - Bold (Underscore).sublime-macro"}, "context": + [ + { "key": "selector", "operator": "equal", "operand": "text.html.markdown - meta.frontmatter - meta.disable-markdown - markup.raw - markup.kbd - markup.bold - markup.bold_italic", "match_all": true }, + { "key": "setting.mde.bold_marker_asterisk", "operator": "equal", "operand": false }, + { "key": "selection_empty", "operator": "equal", "operand": true, "match_all": true }, + { "key": "following_text", "operator": "regex_contains", "operand": "^\\w", "match_all": true } + ] + }, + // Transform selection to bold + { "keys": ["alt+b"], "command": "insert_snippet", "args": {"contents": "**${SELECTION/^\\*\\*|^__|\\*\\*$|__$//g}**"}, "context": + [ + { "key": "selector", "operator": "equal", "operand": "text.html.markdown - meta.frontmatter - meta.disable-markdown - markup.raw - markup.kbd - markup.bold - markup.bold_italic", "match_all": true }, + { "key": "setting.mde.bold_marker_asterisk", "operator": "equal", "operand": true }, + { "key": "selection_empty", "operator": "equal", "operand": false, "match_all": true }, + { "key": "preceding_text", "operator": "not_regex_contains", "operand": "\\*$|__$", "match_all": true }, + { "key": "following_text", "operator": "not_regex_contains", "operand": "^\\*|^__", "match_all": true } + ] + }, + { "keys": ["alt+b"], "command": "insert_snippet", "args": {"contents": "__${SELECTION/^\\*\\*|^__|\\*\\*$|__$//g}__"}, "context": + [ + { "key": "selector", "operator": "equal", "operand": "text.html.markdown - meta.frontmatter - meta.disable-markdown - markup.raw - markup.kbd - markup.bold - markup.bold_italic", "match_all": true }, + { "key": "setting.mde.bold_marker_asterisk", "operator": "equal", "operand": false }, + { "key": "selection_empty", "operator": "equal", "operand": false, "match_all": true }, + { "key": "preceding_text", "operator": "not_regex_contains", "operand": "\\*$|__$", "match_all": true }, + { "key": "following_text", "operator": "not_regex_contains", "operand": "^\\*|^__", "match_all": true } + ] + }, + // Unbold bold text + { "keys": ["alt+b"], "command": "run_macro_file", "args": {"file": "Packages/MarkdownEditing/macros/Transform Word - Unbold.sublime-macro"}, "context": + [ + { "key": "selector", "operator": "equal", "operand": "text.html.markdown markup.bold - punctuation, text.html.markdown markup.bold_italic - punctuation", "match_all": true } + ] + }, + + // + // Text Formatting Italic + // + + // auto-pair if not within a word + { "keys": ["alt+i"], "command": "insert_snippet", "args": {"contents": "*$0*"}, "context": + [ + { "key": "selector", "operator": "equal", "operand": "text.html.markdown - meta.frontmatter - meta.disable-markdown - markup.raw - markup.kbd - markup.italic - markup.bold_italic", "match_all": true }, + { "key": "setting.mde.italic_marker_asterisk", "operator": "equal", "operand": true }, + { "key": "selection_empty", "operator": "equal", "operand": true, "match_all": true }, + { "key": "eol_selector", "operator": "not_equal", "operand": "string.quoted.single", "match_all": true }, + { "key": "preceding_text", "operator": "not_regex_contains", "operand": "['a-zA-Z0-9_*]$", "match_all": true }, + { "key": "following_text", "operator": "regex_contains", "operand": "^(?:\t| |\\)|]|\\}|$)", "match_all": true } + ] + }, + { "keys": ["alt+i"], "command": "insert_snippet", "args": {"contents": "_$0_"}, "context": + [ + { "key": "selector", "operator": "equal", "operand": "text.html.markdown - meta.frontmatter - meta.disable-markdown - markup.raw - markup.kbd - markup.italic - markup.bold_italic", "match_all": true }, + { "key": "setting.mde.italic_marker_asterisk", "operator": "equal", "operand": false }, + { "key": "selection_empty", "operator": "equal", "operand": true, "match_all": true }, + { "key": "eol_selector", "operator": "not_equal", "operand": "string.quoted.single", "match_all": true }, + { "key": "preceding_text", "operator": "not_regex_contains", "operand": "['a-zA-Z0-9_*]$", "match_all": true }, + { "key": "following_text", "operator": "regex_contains", "operand": "^(?:\t| |\\)|]|\\}|$)", "match_all": true } + ] + }, + // Transform a word to bold if caret is at the beginning, in the middle of or at the end of a word + { "keys": ["alt+i"], "command": "run_macro_file", "args": {"file": "Packages/MarkdownEditing/macros/Transform Word - Italic (Asterisk).sublime-macro"}, "context": + [ + { "key": "selector", "operator": "equal", "operand": "text.html.markdown - meta.frontmatter - meta.disable-markdown - markup.raw - markup.kbd - markup.italic - markup.bold_italic", "match_all": true }, + { "key": "setting.mde.italic_marker_asterisk", "operator": "equal", "operand": true }, + { "key": "selection_empty", "operator": "equal", "operand": true, "match_all": true }, + { "key": "preceding_text", "operator": "regex_contains", "operand": "\\w$", "match_all": true } + ] + }, + { "keys": ["alt+i"], "command": "run_macro_file", "args": {"file": "Packages/MarkdownEditing/macros/Transform Word - Italic (Asterisk).sublime-macro"}, "context": + [ + { "key": "selector", "operator": "equal", "operand": "text.html.markdown - meta.frontmatter - meta.disable-markdown - markup.raw - markup.kbd - markup.italic - markup.bold_italic", "match_all": true }, + { "key": "setting.mde.italic_marker_asterisk", "operator": "equal", "operand": true }, + { "key": "selection_empty", "operator": "equal", "operand": true, "match_all": true }, + { "key": "following_text", "operator": "regex_contains", "operand": "^\\w", "match_all": true } + ] + }, + { "keys": ["alt+i"], "command": "run_macro_file", "args": {"file": "Packages/MarkdownEditing/macros/Transform Word - Italic (Underscore).sublime-macro"}, "context": + [ + { "key": "selector", "operator": "equal", "operand": "text.html.markdown - meta.frontmatter - meta.disable-markdown - markup.raw - markup.kbd - markup.italic - markup.bold_italic", "match_all": true }, + { "key": "setting.mde.italic_marker_asterisk", "operator": "equal", "operand": false }, + { "key": "selection_empty", "operator": "equal", "operand": true, "match_all": true }, + { "key": "preceding_text", "operator": "regex_contains", "operand": "\\w$", "match_all": true } + ] + }, + { "keys": ["alt+i"], "command": "run_macro_file", "args": {"file": "Packages/MarkdownEditing/macros/Transform Word - Italic (Underscore).sublime-macro"}, "context": + [ + { "key": "selector", "operator": "equal", "operand": "text.html.markdown - meta.frontmatter - meta.disable-markdown - markup.raw - markup.kbd - markup.italic - markup.bold_italic", "match_all": true }, + { "key": "setting.mde.italic_marker_asterisk", "operator": "equal", "operand": false }, + { "key": "selection_empty", "operator": "equal", "operand": true, "match_all": true }, + { "key": "following_text", "operator": "regex_contains", "operand": "^\\w", "match_all": true } + ] + }, + // Transform selection to italics + { "keys": ["alt+i"], "command": "insert_snippet", "args": {"contents": "*${SELECTION/(^[\\*_]*|[\\*_]*$)//g}*"}, "context": + [ + { "key": "selector", "operator": "equal", "operand": "text.html.markdown - meta.frontmatter - meta.disable-markdown - markup.raw - markup.kbd - markup.italic - markup.bold_italic", "match_all": true }, + { "key": "setting.mde.italic_marker_asterisk", "operator": "equal", "operand": true }, + { "key": "selection_empty", "operator": "equal", "operand": false, "match_all": true }, + { "key": "preceding_text", "operator": "not_regex_contains", "operand": "\\*$|_$", "match_all": true }, + { "key": "following_text", "operator": "not_regex_contains", "operand": "^\\*|^_", "match_all": true } + ] + }, + // Remove italics style from text + { "keys": ["alt+i"], "command": "insert_snippet", "args": {"contents": "_${SELECTION/(^[\\*_]*|[\\*_]*$)//g}_"}, "context": + [ + { "key": "selector", "operator": "equal", "operand": "text.html.markdown - meta.frontmatter - meta.disable-markdown - markup.raw - markup.kbd - markup.italic - markup.bold_italic", "match_all": true }, + { "key": "setting.mde.italic_marker_asterisk", "operator": "equal", "operand": false }, + { "key": "selection_empty", "operator": "equal", "operand": false, "match_all": true }, + { "key": "preceding_text", "operator": "not_regex_contains", "operand": "\\*$|_$", "match_all": true }, + { "key": "following_text", "operator": "not_regex_contains", "operand": "^\\*|^_", "match_all": true } + ] + }, + { "keys": ["alt+i"], "command": "run_macro_file", "args": {"file": "Packages/MarkdownEditing/macros/Transform Word - Unitalicize.sublime-macro"}, "context": + [ + { "key": "selector", "operator": "equal", "operand": "text.html.markdown markup.italic - punctuation, text.html.markdown markup.bold_italic - punctuation", "match_all": true } + ] + }, + + // + // Headings + // + + { "keys": ["ctrl+alt+keypad0"], "command": "mde_change_headings_level", "args": {"to": 0}, "context": + [ + { "key": "selector", "operator": "equal", "operand": "text.html.markdown - meta.frontmatter - meta.disable-markdown - markup.raw", "match_all": true } + ] + }, + { "keys": ["ctrl+alt+0"], "command": "mde_change_headings_level", "args": {"to": 0}, "context": + [ + { "key": "selector", "operator": "equal", "operand": "text.html.markdown - meta.frontmatter - meta.disable-markdown - markup.raw", "match_all": true } + ] + }, + { "keys": ["ctrl+alt+keypad1"], "command": "mde_change_headings_level", "args": {"to": 1}, "context": + [ + { "key": "selector", "operator": "equal", "operand": "text.html.markdown - meta.frontmatter - meta.disable-markdown - markup.raw", "match_all": true } + ] + }, + { "keys": ["ctrl+alt+1"], "command": "mde_change_headings_level", "args": {"to": 1}, "context": + [ + { "key": "selector", "operator": "equal", "operand": "text.html.markdown - meta.frontmatter - meta.disable-markdown - markup.raw", "match_all": true } + ] + }, + { "keys": ["ctrl+alt+keypad2"], "command": "mde_change_headings_level", "args": {"to": 2}, "context": + [ + { "key": "selector", "operator": "equal", "operand": "text.html.markdown - meta.frontmatter - meta.disable-markdown - markup.raw", "match_all": true } + ] + }, + { "keys": ["ctrl+alt+2"], "command": "mde_change_headings_level", "args": {"to": 2}, "context": + [ + { "key": "selector", "operator": "equal", "operand": "text.html.markdown - meta.frontmatter - meta.disable-markdown - markup.raw", "match_all": true } + ] + }, + { "keys": ["ctrl+alt+keypad3"], "command": "mde_change_headings_level", "args": {"to": 3}, "context": + [ + { "key": "selector", "operator": "equal", "operand": "text.html.markdown - meta.frontmatter - meta.disable-markdown - markup.raw", "match_all": true } + ] + }, + { "keys": ["ctrl+alt+3"], "command": "mde_change_headings_level", "args": {"to": 3}, "context": + [ + { "key": "selector", "operator": "equal", "operand": "text.html.markdown - meta.frontmatter - meta.disable-markdown - markup.raw", "match_all": true } + ] + }, + { "keys": ["ctrl+alt+keypad4"], "command": "mde_change_headings_level", "args": {"to": 4}, "context": + [ + { "key": "selector", "operator": "equal", "operand": "text.html.markdown - meta.frontmatter - meta.disable-markdown - markup.raw", "match_all": true } + ] + }, + { "keys": ["ctrl+alt+4"], "command": "mde_change_headings_level", "args": {"to": 4}, "context": + [ + { "key": "selector", "operator": "equal", "operand": "text.html.markdown - meta.frontmatter - meta.disable-markdown - markup.raw", "match_all": true } + ] + }, + { "keys": ["ctrl+alt+keypad5"], "command": "mde_change_headings_level", "args": {"to": 5}, "context": + [ + { "key": "selector", "operator": "equal", "operand": "text.html.markdown - meta.frontmatter - meta.disable-markdown - markup.raw", "match_all": true } + ] + }, + { "keys": ["ctrl+alt+5"], "command": "mde_change_headings_level", "args": {"to": 5}, "context": + [ + { "key": "selector", "operator": "equal", "operand": "text.html.markdown - meta.frontmatter - meta.disable-markdown - markup.raw", "match_all": true } + ] + }, + { "keys": ["ctrl+alt+keypad6"], "command": "mde_change_headings_level", "args": {"to": 6}, "context": + [ + { "key": "selector", "operator": "equal", "operand": "text.html.markdown - meta.frontmatter - meta.disable-markdown - markup.raw", "match_all": true } + ] + }, + { "keys": ["ctrl+alt+6"], "command": "mde_change_headings_level", "args": {"to": 6}, "context": + [ + { "key": "selector", "operator": "equal", "operand": "text.html.markdown - meta.frontmatter - meta.disable-markdown - markup.raw", "match_all": true } + ] + }, + { "keys": ["ctrl+alt+."], "command": "mde_change_headings_level", "args": {"by": 1}, "context": + [ + { "key": "selector", "operator": "equal", "operand": "text.html.markdown - meta.frontmatter - meta.disable-markdown - markup.raw", "match_all": true } + ] + }, + { "keys": ["ctrl+alt+,"], "command": "mde_change_headings_level", "args": {"by": -1}, "context": + [ + { "key": "selector", "operator": "equal", "operand": "text.html.markdown - meta.frontmatter - meta.disable-markdown - markup.raw", "match_all": true } + ] + }, + // If nothing is selected, pressing hash in front of heading label increases level by one + { "keys": ["#"], "command": "mde_change_headings_level", "args": {"by": 1}, "context": + [ + { "key": "selector", "operator": "equal", "operand": "text.html.markdown - meta.frontmatter - meta.disable-markdown - markup.raw - markup.kbd", "match_all": true }, + { "key": "setting.mde.auto_match_heading_hashes", "operator": "equal", "operand": true }, + { "key": "selection_empty", "operator": "equal", "operand": true, "match_all": true }, + { "key": "preceding_text", "operator": "regex_match", "operand": "^[\\s>]*#*\\s*$", "match_all": true } + ] + }, + // If nothing is selected, pressing backspace within or directly after leading hashes decreases heading level + { "keys": ["backspace"], "command": "mde_change_headings_level", "args": {"by": -1}, "context": + [ + { "key": "selector", "operator": "equal", "operand": "text.html.markdown - meta.frontmatter - meta.disable-markdown - markup.raw - markup.kbd", "match_all": true }, + { "key": "setting.mde.auto_match_heading_hashes", "operator": "equal", "operand": true }, + { "key": "selection_empty", "operator": "equal", "operand": true, "match_all": true }, + { "key": "preceding_text", "operator": "regex_match", "operand": "^[\\s>]*#+\\s?$", "match_all": true } + ] + }, + // If nothing is selected, pressing delete within or directly in front of leading hashes decreases heading level + { "keys": ["delete"], "command": "mde_change_headings_level", "args": {"by": -1}, "context": + [ + { "key": "selector", "operator": "equal", "operand": "text.html.markdown - meta.frontmatter - meta.disable-markdown - markup.raw - markup.kbd", "match_all": true }, + { "key": "setting.mde.auto_match_heading_hashes", "operator": "equal", "operand": true }, + { "key": "selection_empty", "operator": "equal", "operand": true, "match_all": true }, + { "key": "preceding_text", "operator": "regex_match", "operand": "^[\\s>]*#*\\s*$", "match_all": true }, + { "key": "following_text", "operator": "regex_contains", "operand": "^#", "match_all": true } + ] + }, + { "keys": ["enter"], "command": "run_macro_file", "args": {"file": "Packages/MarkdownEditing/macros/Balance Trailing Hashes.sublime-macro"}, "context": + [ + { "key": "selector", "operator": "equal", "operand": "text.html.markdown - meta.frontmatter - meta.disable-markdown - markup.raw - markup.kbd", "match_all": true }, + { "key": "setting.mde.auto_match_heading_hashes", "operator": "equal", "operand": true }, + { "key": "setting.mde.match_heading_hashes", "operator": "equal", "operand": true }, + { "key": "preceding_text", "operator": "regex_contains", "operand": "^[\\s>]*#+\\s+", "match_all": true }, + { "key": "following_text", "operator": "regex_contains", "operand": "^\\s*$", "match_all": true }, + { "key": "auto_complete_visible", "operator": "equal", "operand": false } + ] + }, + { "keys": ["enter"], "command": "run_macro_file", "args": {"file": "Packages/MarkdownEditing/macros/Balance Trailing Hashes.sublime-macro"}, "context": + [ + { "key": "selector", "operator": "equal", "operand": "text.html.markdown - meta.frontmatter - meta.disable-markdown - markup.raw - markup.kbd", "match_all": true }, + { "key": "setting.mde.auto_match_heading_hashes", "operator": "equal", "operand": true }, + { "key": "setting.mde.match_heading_hashes", "operator": "equal", "operand": true }, + { "key": "preceding_text", "operator": "regex_contains", "operand": "^[\\s>]*#+\\s+", "match_all": true }, + { "key": "following_text", "operator": "regex_contains", "operand": "^\\s*$", "match_all": true }, + { "key": "setting.auto_complete_commit_on_tab" } + ] + }, + { "keys": ["enter"], "command": "run_macro_file", "args": {"file": "Packages/MarkdownEditing/macros/Remove Trailing Hashes.sublime-macro"}, "context": + [ + { "key": "selector", "operator": "equal", "operand": "text.html.markdown - meta.frontmatter - meta.disable-markdown - markup.raw - markup.kbd", "match_all": true }, + { "key": "setting.mde.auto_match_heading_hashes", "operator": "equal", "operand": true }, + { "key": "setting.mde.match_heading_hashes", "operator": "equal", "operand": false }, + { "key": "preceding_text", "operator": "regex_contains", "operand": "^[\\s>]*#+\\s+", "match_all": true }, + { "key": "following_text", "operator": "regex_contains", "operand": "^\\s*$", "match_all": true }, + { "key": "auto_complete_visible", "operator": "equal", "operand": false } + ] + }, + { "keys": ["enter"], "command": "run_macro_file", "args": {"file": "Packages/MarkdownEditing/macros/Remove Trailing Hashes.sublime-macro"}, "context": + [ + { "key": "selector", "operator": "equal", "operand": "text.html.markdown - meta.frontmatter - meta.disable-markdown - markup.raw - markup.kbd", "match_all": true }, + { "key": "setting.mde.auto_match_heading_hashes", "operator": "equal", "operand": true }, + { "key": "setting.mde.match_heading_hashes", "operator": "equal", "operand": false }, + { "key": "preceding_text", "operator": "regex_contains", "operand": "^[\\s>]*#+\\s+", "match_all": true }, + { "key": "following_text", "operator": "regex_contains", "operand": "^\\s*$", "match_all": true }, + { "key": "setting.auto_complete_commit_on_tab" } + ] + }, + { "keys": ["tab"], "command": "mde_complete_underlined_headings", "context": + [ + { "key": "selector", "operator": "equal", "operand": "text.html.markdown - meta.frontmatter - meta.disable-markdown - markup.raw - markup.kbd", "match_all": true }, + { "key": "selection_empty", "operator": "equal", "operand": true, "match_all": true }, + { "key": "preceding_text", "operator": "regex_contains", "operand": "^\\-+$|^\\=+$", "match_all": true }, + { "key": "auto_complete_visible", "operator": "equal", "operand": false, "match_all": true } + ] + }, + { "keys": ["ctrl+shift+alt+pageup"], "command": "mde_goto_previous_heading", "args": {"same_level": true}, "context": + [ + { "key": "selector", "operator": "equal", "operand": "text.html.markdown", "match_all": true }, + { "key": "setting.mde.keymap_disable.goto_previous_heading", "operator": "not_equal", "operand": true } + ] + }, + { "keys": ["ctrl+shift+alt+pagedown"], "command": "mde_goto_next_heading", "args": {"same_level": true}, "context": + [ + { "key": "selector", "operator": "equal", "operand": "text.html.markdown", "match_all": true }, + { "key": "setting.mde.keymap_disable.goto_next_heading", "operator": "not_equal", "operand": true } + ] + }, + { "keys": ["ctrl+shift+pageup"], "command": "mde_goto_previous_heading", "args": {"same_level": false}, "context": + [ + { "key": "selector", "operator": "equal", "operand": "text.html.markdown", "match_all": true }, + { "key": "setting.mde.keymap_disable.goto_previous_heading", "operator": "not_equal", "operand": true } + ] + }, + { "keys": ["ctrl+shift+pagedown"], "command": "mde_goto_next_heading", "args": {"same_level": false}, "context": + [ + { "key": "selector", "operator": "equal", "operand": "text.html.markdown", "match_all": true }, + { "key": "setting.mde.keymap_disable.goto_next_heading", "operator": "not_equal", "operand": true } + ] + }, + + // + // Folding + // + + { "keys": ["ctrl+k", "ctrl+keypad0"], "command": "mde_unfold_all_sections", "context": + [ + { "key": "selector", "operator": "equal", "operand": "text.html.markdown - meta.frontmatter - meta.disable-markdown - markup.raw", "match_all": true } + ] + }, + { "keys": ["ctrl+k", "ctrl+0"], "command": "mde_unfold_all_sections", "context": + [ + { "key": "selector", "operator": "equal", "operand": "text.html.markdown - meta.frontmatter - meta.disable-markdown - markup.raw", "match_all": true } + ] + }, + { "keys": ["ctrl+k", "ctrl+keypad1"], "command": "mde_fold_all_sections", "args": {"target_level": 1}, "context": + [ + { "key": "selector", "operator": "equal", "operand": "text.html.markdown - meta.frontmatter - meta.disable-markdown - markup.raw", "match_all": true } + ] + }, + { "keys": ["ctrl+k", "ctrl+1"], "command": "mde_fold_all_sections", "args": {"target_level": 1}, "context": + [ + { "key": "selector", "operator": "equal", "operand": "text.html.markdown - meta.frontmatter - meta.disable-markdown - markup.raw", "match_all": true } + ] + }, + { "keys": ["ctrl+k", "ctrl+keypad2"], "command": "mde_fold_all_sections", "args": {"target_level": 2}, "context": + [ + { "key": "selector", "operator": "equal", "operand": "text.html.markdown - meta.frontmatter - meta.disable-markdown - markup.raw", "match_all": true } + ] + }, + { "keys": ["ctrl+k", "ctrl+2"], "command": "mde_fold_all_sections", "args": {"target_level": 2}, "context": + [ + { "key": "selector", "operator": "equal", "operand": "text.html.markdown - meta.frontmatter - meta.disable-markdown - markup.raw", "match_all": true } + ] + }, + { "keys": ["ctrl+k", "ctrl+keypad3"], "command": "mde_fold_all_sections", "args": {"target_level": 3}, "context": + [ + { "key": "selector", "operator": "equal", "operand": "text.html.markdown - meta.frontmatter - meta.disable-markdown - markup.raw", "match_all": true } + ] + }, + { "keys": ["ctrl+k", "ctrl+3"], "command": "mde_fold_all_sections", "args": {"target_level": 3}, "context": + [ + { "key": "selector", "operator": "equal", "operand": "text.html.markdown - meta.frontmatter - meta.disable-markdown - markup.raw", "match_all": true } + ] + }, + { "keys": ["ctrl+k", "ctrl+keypad4"], "command": "mde_fold_all_sections", "args": {"target_level": 4}, "context": + [ + { "key": "selector", "operator": "equal", "operand": "text.html.markdown - meta.frontmatter - meta.disable-markdown - markup.raw", "match_all": true } + ] + }, + { "keys": ["ctrl+k", "ctrl+4"], "command": "mde_fold_all_sections", "args": {"target_level": 4}, "context": + [ + { "key": "selector", "operator": "equal", "operand": "text.html.markdown - meta.frontmatter - meta.disable-markdown - markup.raw", "match_all": true } + ] + }, + { "keys": ["ctrl+k", "ctrl+keypad5"], "command": "mde_fold_all_sections", "args": {"target_level": 5}, "context": + [ + { "key": "selector", "operator": "equal", "operand": "text.html.markdown - meta.frontmatter - meta.disable-markdown - markup.raw", "match_all": true } + ] + }, + { "keys": ["ctrl+k", "ctrl+5"], "command": "mde_fold_all_sections", "args": {"target_level": 5}, "context": + [ + { "key": "selector", "operator": "equal", "operand": "text.html.markdown - meta.frontmatter - meta.disable-markdown - markup.raw", "match_all": true } + ] + }, + { "keys": ["ctrl+k", "ctrl+keypad6"], "command": "mde_fold_all_sections", "args": {"target_level": 6}, "context": + [ + { "key": "selector", "operator": "equal", "operand": "text.html.markdown - meta.frontmatter - meta.disable-markdown - markup.raw", "match_all": true } + ] + }, + { "keys": ["ctrl+k", "ctrl+6"], "command": "mde_fold_all_sections", "args": {"target_level": 6}, "context": + [ + { "key": "selector", "operator": "equal", "operand": "text.html.markdown - meta.frontmatter - meta.disable-markdown - markup.raw", "match_all": true } + ] + }, + { "keys": ["ctrl+k", "ctrl+keypad9"], "command": "mde_fold_all_sections", "args": {"target_level": 0}, "context": + [ + { "key": "selector", "operator": "equal", "operand": "text.html.markdown - meta.frontmatter - meta.disable-markdown - markup.raw", "match_all": true } + ] + }, + { "keys": ["ctrl+k", "ctrl+9"], "command": "mde_fold_all_sections", "args": {"target_level": 0}, "context": + [ + { "key": "selector", "operator": "equal", "operand": "text.html.markdown - meta.frontmatter - meta.disable-markdown - markup.raw", "match_all": true } + ] + }, + { "keys": ["shift+tab"], "command": "mde_fold_section", "context": + [ + { "key": "selector", "operator": "equal", "operand": "text.html.markdown - meta.frontmatter - meta.disable-markdown - markup.raw - markup.list", "match_all": true }, + { "key": "setting.mde.keymap_disable.fold_section", "operator": "not_equal", "operand": true }, + { "key": "selection_empty", "operator": "equal", "operand": true, "match_all": true }, + { "key": "has_prev_field", "operator": "equal", "operand": false }, + { "key": "overlay_visible", "operator": "equal", "operand": false }, + { "key": "preceding_text", "operator": "not_regex_match", "operand": "^\\s+", "match_all": true } + ] + }, + { "keys": ["shift+tab"], "command": "mde_fold_section", "context": + [ + { "key": "selector", "operator": "equal", "operand": "text.html.markdown", "match_all": true }, + { "key": "setting.mde.keymap_disable.fold_section", "operator": "not_equal", "operand": true }, + { "key": "selection_empty", "operator": "equal", "operand": false, "match_all": true }, + { "key": "has_prev_field", "operator": "equal", "operand": false }, + { "key": "overlay_visible", "operator": "equal", "operand": false }, + { "key": "text", "operator": "regex_contains", "operand": "^(#{1,6}(?!#))|^(-{3,}|={3,})$"} + ] + }, + { "keys": ["ctrl+shift+tab"], "command": "mde_show_fold_all_sections", "context": + [ + { "key": "selector", "operator": "equal", "operand": "text.html.markdown", "match_all": true }, + { "key": "setting.mde.keymap_disable.show_fold_all_sections", "operator": "not_equal", "operand": true } + ] + }, + + // + // Lists + // + + // Create new GFM Task + { "keys": ["alt+t"], "command": "insert_snippet", "args": {"contents": "* [ ] $0"}, "context": + [ + { "key": "selector", "operator": "equal", "operand": "text.html.markdown - meta.frontmatter - meta.disable-markdown - markup.raw - markup.kbd - meta.table", "match_all": true }, + { "key": "setting.auto_match_enabled", "operator": "equal", "operand": true }, + { "key": "setting.mde.list_align_text", "operator": "equal", "operand": false }, + { "key": "selection_empty", "operator": "equal", "operand": true, "match_all": true }, + { "key": "preceding_text", "operator": "regex_match", "operand": "^[\\s>]*$", "match_all": true }, + { "key": "following_text", "operator": "regex_match", "operand": "^\\s*$", "match_all": true } + ] + }, + { "keys": ["alt+t"], "command": "insert_snippet", "args": {"contents": "* [ ]\t$0"}, "context": + [ + { "key": "selector", "operator": "equal", "operand": "text.html.markdown - meta.frontmatter - meta.disable-markdown - markup.raw - markup.kbd - meta.table", "match_all": true }, + { "key": "setting.auto_match_enabled", "operator": "equal", "operand": true }, + { "key": "setting.mde.list_align_text", "operator": "equal", "operand": true }, + { "key": "selection_empty", "operator": "equal", "operand": true, "match_all": true }, + { "key": "preceding_text", "operator": "regex_match", "operand": "^[\\s>]*$", "match_all": true }, + { "key": "following_text", "operator": "regex_match", "operand": "^\\s*$", "match_all": true } + ] + }, + // Convert List Item to GFM Task + { "keys": ["alt+t"], "command": "run_macro_file", "args": {"file": "Packages/MarkdownEditing/macros/Convert List to Task.sublime-macro"}, "context": + [ + { "key": "selector", "operator": "equal", "operand": "text.html.markdown - meta.frontmatter - meta.disable-markdown - markup.raw - markup.kbd - meta.table", "match_all": true }, + { "key": "setting.auto_match_enabled", "operator": "equal", "operand": true }, + { "key": "setting.mde.list_align_text", "operator": "equal", "operand": false }, + { "key": "selection_empty", "operator": "equal", "operand": true, "match_all": true }, + { "key": "preceding_text", "operator": "regex_match", "operand": "^[\\s>]*[-+*]\\s+$", "match_all": true }, + { "key": "following_text", "operator": "regex_match", "operand": "^\\s*$", "match_all": true } + ] + }, + { "keys": ["alt+t"], "command": "run_macro_file", "args": {"file": "Packages/MarkdownEditing/macros/Convert List to Task Tab.sublime-macro"}, "context": + [ + { "key": "selector", "operator": "equal", "operand": "text.html.markdown - meta.frontmatter - meta.disable-markdown - markup.raw - markup.kbd - meta.table", "match_all": true }, + { "key": "setting.auto_match_enabled", "operator": "equal", "operand": true }, + { "key": "setting.mde.list_align_text", "operator": "equal", "operand": true }, + { "key": "selection_empty", "operator": "equal", "operand": true, "match_all": true }, + { "key": "preceding_text", "operator": "regex_match", "operand": "^[\\s>]*[-+*]\\s+$", "match_all": true }, + { "key": "following_text", "operator": "regex_match", "operand": "^\\s*$", "match_all": true } + ] + }, + // Add line to current list item + { "keys": ["shift+enter"], "command": "insert_snippet", "args": {"contents": "${TM_CURRENT_LINE/^(?:\\s*((?:>\\s*)*)([-+*])(\\s+)).*/\n$1 $3/}"}, "context": + [ + { "key": "selector", "operator": "equal", "operand": "text.html.markdown - markup.raw", "match_all": true }, + { "key": "preceding_text", "operator": "regex_contains", "operand": "^[\\s>]*[-+*](?:\\s+\\S|\\s*$)", "match_all": true } + ] + }, + // Extend lists (also in block quotes) + { "keys": ["enter"], "command": "insert_snippet", "args": {"contents": "${TM_CURRENT_LINE/^(?:\\s*((?:>\\s*)*)([-+*])(\\s+)).*/\n$1$2$3/}"}, "context": + [ + { "key": "selector", "operator": "equal", "operand": "text.html.markdown - meta.frontmatter - meta.disable-markdown - markup.raw", "match_all": true }, + { "key": "preceding_text", "operator": "regex_contains", "operand": "^[\\s>]*[-+*](?:\\s+\\S|\\s*$)", "match_all": true }, + { "key": "auto_complete_visible", "operator": "equal", "operand": false } + ] + }, + { "keys": ["enter"], "command": "insert_snippet", "args": {"contents": "${TM_CURRENT_LINE/^(?:\\s*((?:>\\s*)*)([-+*])(\\s+)).*/\n$1$2$3/}"}, "context": + [ + { "key": "selector", "operator": "equal", "operand": "text.html.markdown - meta.frontmatter - meta.disable-markdown - markup.raw", "match_all": true }, + { "key": "preceding_text", "operator": "regex_contains", "operand": "^[\\s>]*[-+*](?:\\s+\\S|\\s*$)", "match_all": true }, + { "key": "setting.auto_complete_commit_on_tab" } + ] + }, + // Extend lists with GFM tasks (also in block quotes) + { "keys": ["enter"], "command": "insert_snippet", "args": {"contents": "${TM_CURRENT_LINE/^(?:\\s*((?:>\\s*)*)([-+*])(\\s+)\\[[ xX]\\](\\s+)).*/\n$1$2$3[ ]$4/}"}, "context": + [ + { "key": "selector", "operator": "equal", "operand": "text.html.markdown - meta.frontmatter - meta.disable-markdown - markup.raw", "match_all": true }, + { "key": "preceding_text", "operator": "regex_contains", "operand": "^([\\s>]*([-+*])\\s+)\\[[ xX]\\](?:\\s+\\S|\\s*$)", "match_all": true }, + { "key": "auto_complete_visible", "operator": "equal", "operand": false } + ] + }, + { "keys": ["enter"], "command": "insert_snippet", "args": {"contents": "${TM_CURRENT_LINE/^(?:\\s*((?:>\\s*)*)([-+*])(\\s+)\\[[ xX]\\](\\s+)).*/\n$1$2$3[ ]$4/}"}, "context": + [ + { "key": "selector", "operator": "equal", "operand": "text.html.markdown - meta.frontmatter - meta.disable-markdown - markup.raw", "match_all": true }, + { "key": "preceding_text", "operator": "regex_contains", "operand": "^([\\s>]*([-+*])\\s+)\\[[ xX]\\](?:\\s+\\S|\\s*$)", "match_all": true }, + { "key": "setting.auto_complete_commit_on_tab" } + ] + }, + // Extend Numbered Lists (also in block quotes) + { "keys": ["enter"], "command": "mde_number_list", "context": + [ + { "key": "selector", "operator": "equal", "operand": "text.html.markdown - meta.frontmatter - meta.disable-markdown - markup.raw", "match_all": true }, + { "key": "preceding_text", "operator": "regex_contains", "operand": "^[\\s>]*\\d+[.)]", "match_all": true }, + { "key": "auto_complete_visible", "operator": "equal", "operand": false } + ] + }, + { "keys": ["enter"], "command": "mde_number_list", "context": + [ + { "key": "selector", "operator": "equal", "operand": "text.html.markdown - meta.frontmatter - meta.disable-markdown - markup.raw", "match_all": true }, + { "key": "preceding_text", "operator": "regex_contains", "operand": "^[\\s>]*\\d+[.)]", "match_all": true }, + { "key": "setting.auto_complete_commit_on_tab" } + ] + }, + // Remove empty list item including GFM tasks + { "keys": ["enter"], "command": "run_macro_file", "args": {"file": "Packages/MarkdownEditing/macros/Remove Empty List Item.sublime-macro"}, "context": + [ + { "key": "selector", "operator": "equal", "operand": "text.html.markdown - meta.frontmatter - meta.disable-markdown - markup.raw", "match_all": true }, + { "key": "preceding_text", "operator": "regex_match", "operand": "^[\\s>]*([-+*]|\\d+[.)])(?:\\s+\\[[ xX]\\])?\\s*$", "match_all": true }, + { "key": "following_text", "operator": "regex_match", "operand": "^\\s*$", "match_all": true }, + { "key": "auto_complete_visible", "operator": "equal", "operand": false } + ] + }, + { "keys": ["enter"], "command": "run_macro_file", "args": {"file": "Packages/MarkdownEditing/macros/Remove Empty List Item.sublime-macro"}, "context": + [ + { "key": "selector", "operator": "equal", "operand": "text.html.markdown - meta.frontmatter - meta.disable-markdown - markup.raw", "match_all": true }, + { "key": "preceding_text", "operator": "regex_match", "operand": "^[\\s>]*([-+*]|\\d+[.)])(?:\\s+\\[[ xX]\\])?\\s*$", "match_all": true }, + { "key": "following_text", "operator": "regex_match", "operand": "^\\s*$", "match_all": true }, + { "key": "setting.auto_complete_commit_on_tab" } + ] + }, + { "keys": ["backspace"], "command": "run_macro_file", "args": {"file": "Packages/MarkdownEditing/macros/Remove Empty List Item.sublime-macro"}, "context": + [ + { "key": "selector", "operator": "equal", "operand": "text.html.markdown - meta.frontmatter - meta.disable-markdown - markup.raw", "match_all": true }, + { "key": "preceding_text", "operator": "regex_match", "operand": "^[\\s>]*([-+*]|\\d+[.)])(?:\\s+\\[[ xX]\\])?\\s?$", "match_all": true }, + { "key": "following_text", "operator": "regex_match", "operand": "^\\s*$", "match_all": true } + ] + }, + // Join content of next into current line after removing its leading blockquote, list and GFM task punctuation + { "keys": ["delete"], "command": "mde_join_lines", "context": + [ + { "key": "selector", "operator": "equal", "operand": "text.html.markdown markup.quote, text.html.markdown markup.list" }, + { "key": "selection_empty", "operator": "equal", "operand": true, "match_all": true }, + { "key": "following_text", "operator": "regex_match", "operand": "^$", "match_all": true } + ] + }, + { "keys": ["ctrl+shift+j"], "command": "mde_join_lines", "context": + [ + { "key": "selector", "operator": "equal", "operand": "text.html.markdown markup.quote, text.html.markdown markup.list" } + ] + }, + // Indent list item if caret is in front of bullets + { "keys": ["tab"], "command": "mde_indent_list_item", "context": + [ + { "key": "selector", "operator": "equal", "operand": "text.html.markdown - meta.frontmatter - meta.disable-markdown - markup.raw", "match_all": true }, + { "key": "selection_empty", "operator": "equal", "operand": true, "match_all": true }, + { "key": "has_next_field", "operator": "equal", "operand": false }, + { "key": "overlay_visible", "operator": "equal", "operand": false }, + { "key": "preceding_text", "operator": "regex_match", "operand": "^[\\s>]*$", "match_all": true }, + { "key": "following_text", "operator": "regex_contains", "operand": "^\\s*[-+*]\\s", "match_all": true } + ] + }, + // Indent list item, if caret is directly behind bullet only if followed by whitespace + // Hitting "tab" directly after new list bullet should insert \t otherwise + { "keys": ["tab"], "command": "mde_indent_list_item", "context": + [ + { "key": "selector", "operator": "equal", "operand": "text.html.markdown - meta.frontmatter - meta.disable-markdown - markup.raw", "match_all": true }, + { "key": "selection_empty", "operator": "equal", "operand": true, "match_all": true }, + { "key": "has_next_field", "operator": "equal", "operand": false }, + { "key": "overlay_visible", "operator": "equal", "operand": false }, + { "key": "preceding_text", "operator": "regex_match", "operand": "^[\\s>]*[-+*]$", "match_all": true }, + { "key": "following_text", "operator": "regex_contains", "operand": "^\\s", "match_all": true } + ] + }, + // Indent list item if caret is behind bullets + { "keys": ["tab"], "command": "mde_indent_list_item", "context": + [ + { "key": "selector", "operator": "equal", "operand": "text.html.markdown - meta.frontmatter - meta.disable-markdown - markup.raw", "match_all": true }, + { "key": "selection_empty", "operator": "equal", "operand": true, "match_all": true }, + { "key": "has_next_field", "operator": "equal", "operand": false }, + { "key": "overlay_visible", "operator": "equal", "operand": false }, + { "key": "preceding_text", "operator": "regex_match", "operand": "^[\\s>]*[-+*]\\s*$", "match_all": true }, + { "key": "following_text", "operator": "not_regex_match", "operand": "(?:-{2,}|={2,}|[+*])", "match_all": true } + ] + }, + // Indent selected list items + { "keys": ["tab"], "command": "mde_indent_list_item", "context": + [ + { "key": "selector", "operator": "equal", "operand": "text.html.markdown - meta.frontmatter - meta.disable-markdown - markup.raw", "match_all": true }, + { "key": "selection_empty", "operator": "equal", "operand": false, "match_all": true }, + { "key": "has_next_field", "operator": "equal", "operand": false }, + { "key": "overlay_visible", "operator": "equal", "operand": false } + ] + }, + // Unindent list item no matter of caret position if `shift_tab_unindent` is set + { "keys": ["shift+tab"], "command": "mde_unindent_list_item", "context": + [ + { "key": "selector", "operator": "equal", "operand": "text.html.markdown", "match_all": true }, + { "key": "setting.shift_tab_unindent", "operator": "equal", "operand": true }, + { "key": "has_prev_field", "operator": "equal", "operand": false }, + { "key": "overlay_visible", "operator": "equal", "operand": false }, + { "key": "preceding_text", "operator": "regex_contains", "operand": "^[\\s>]*[-+*]\\s", "match_all": true } + ] + }, + // Unindent list item if caret is in front of bullets + { "keys": ["shift+tab"], "command": "mde_unindent_list_item", "context": + [ + { "key": "selector", "operator": "equal", "operand": "text.html.markdown", "match_all": true }, + { "key": "has_prev_field", "operator": "equal", "operand": false }, + { "key": "overlay_visible", "operator": "equal", "operand": false }, + { "key": "preceding_text", "operator": "regex_match", "operand": "^[\\s>]*$", "match_all": true }, + { "key": "following_text", "operator": "regex_contains", "operand": "^\\s*[-+*]\\s", "match_all": true } + ] + }, + // Unindent list item if caret is behind bullets + { "keys": ["shift+tab"], "command": "mde_unindent_list_item", "context": + [ + { "key": "selector", "operator": "equal", "operand": "text.html.markdown", "match_all": true }, + { "key": "has_prev_field", "operator": "equal", "operand": false }, + { "key": "overlay_visible", "operator": "equal", "operand": false }, + { "key": "preceding_text", "operator": "regex_match", "operand": "^[\\s>]*[-+*]\\s*$", "match_all": true }, + { "key": "following_text", "operator": "not_regex_match", "operand": "(?:-{2,}|={2,})", "match_all": true } + ] + }, + // Unindent list item if caret is at eol + { "keys": ["shift+tab"], "command": "mde_unindent_list_item", "context": + [ + { "key": "selector", "operator": "equal", "operand": "text.html.markdown", "match_all": true }, + { "key": "has_prev_field", "operator": "equal", "operand": false }, + { "key": "overlay_visible", "operator": "equal", "operand": false }, + { "key": "preceding_text", "operator": "regex_contains", "operand": "^[\\s>]*[-+*]\\s", "match_all": true }, + { "key": "following_text", "operator": "regex_match", "operand": "^$" } + ] + }, + // Unindent selected list items + { "keys": ["shift+tab"], "command": "mde_unindent_list_item", "context": + [ + { "key": "selector", "operator": "equal", "operand": "text.html.markdown markup.list", "match_all": true }, + { "key": "selection_empty", "operator": "equal", "operand": false, "match_all": true }, + { "key": "has_prev_field", "operator": "equal", "operand": false }, + { "key": "overlay_visible", "operator": "equal", "operand": false } + ] + }, + // Toggle GFM tasks + { "keys": ["alt+x"], "command": "mde_toggle_task_list_item", "context": + [ + { "key": "selector", "operator": "equal", "operand": "text.html.markdown & (markup.list | markup.quote)", "match_all": true } + ] + }, + + // + // Quotes + // + + // Convert to blockquote + { "keys": [">"], "command": "run_macro_file", "args": {"file": "Packages/MarkdownEditing/macros/Convert to Blockquote.sublime-macro"}, "context": + [ + { "key": "selector", "operator": "equal", "operand": "text.html.markdown - meta.frontmatter - meta.disable-markdown - markup.raw - markup.kbd", "match_all": true }, + { "key": "selection_empty", "operator": "equal", "operand": false, "match_all": true } + ] + }, + // Extend blockquote (ignore headings, lists and tasks) + { "keys": ["enter"], "command": "insert_snippet", "args": {"contents": "${TM_CURRENT_LINE/^\\s*((?:>\\s*)*(?:>\\s?)).*/\n$1/}"}, "context": + [ + { "key": "selector", "operator": "equal", "operand": "text.html.markdown markup.quote", "match_all": true }, + { "key": "preceding_text", "operator": "regex_contains", "operand": "^\\s*(?:>\\s*)+(?![-+*>#\\s]|\\d+[.)])", "match_all": true }, + { "key": "auto_complete_visible", "operator": "equal", "operand": false } + ] + }, + { "keys": ["enter"], "command": "insert_snippet", "args": {"contents": "${TM_CURRENT_LINE/^\\s*((?:>\\s*)*(?:>\\s?)).*/\n$1/}"}, "context": + [ + { "key": "selector", "operator": "equal", "operand": "text.html.markdown markup.quote", "match_all": true }, + { "key": "preceding_text", "operator": "regex_contains", "operand": "^\\s*(?:>\\s*)+(?![-+*>#\\s]|\\d+[.)])", "match_all": true }, + { "key": "setting.auto_complete_commit_on_tab" } + ] + }, + // Remove empty blockquote line + // { "keys": ["enter"], "command": "run_macro_file", "args": {"file": "Packages/MarkdownEditing/macros/Remove Empty Blockquote Line.sublime-macro"}, "context": + // [ + // { "key": "selector", "operator": "equal", "operand": "text.html.markdown markup.quote", "match_all": true }, + // { "key": "preceding_text", "operator": "regex_match", "operand": "^\\s*(>\\s*)+$", "match_all": true }, + // { "key": "following_text", "operator": "regex_match", "operand": "^\\s*$", "match_all": true }, + // { "key": "auto_complete_visible", "operator": "equal", "operand": false } + // ] + // }, + // { "keys": ["enter"], "command": "run_macro_file", "args": {"file": "Packages/MarkdownEditing/macros/Remove Empty Blockquote Line.sublime-macro"}, "context": + // [ + // { "key": "selector", "operator": "equal", "operand": "text.html.markdown markup.quote", "match_all": true }, + // { "key": "preceding_text", "operator": "regex_match", "operand": "^\\s*(>\\s*)+$", "match_all": true }, + // { "key": "following_text", "operator": "regex_match", "operand": "^\\s*$", "match_all": true }, + // { "key": "setting.auto_complete_commit_on_tab" } + // ] + // }, + { "keys": ["backspace"], "command": "run_macro_file", "args": {"file": "Packages/MarkdownEditing/macros/Remove Empty Blockquote Line.sublime-macro"}, "context": + [ + { "key": "selector", "operator": "equal", "operand": "text.html.markdown markup.quote", "match_all": true }, + { "key": "preceding_text", "operator": "regex_match", "operand": "^\\s*(>\\s*)*(>\\s?)$", "match_all": true }, + { "key": "following_text", "operator": "regex_match", "operand": "^\\s*$", "match_all": true } + ] + }, + // Indent blockquote + { "keys": ["ctrl+shift+."], "command": "mde_indent_quote", "context": + [ + { "key": "selector", "operator": "equal", "operand": "text.html.markdown", "match_all": true } + ] + }, + // Unindent blockquote + { "keys": ["ctrl+shift+,"], "command": "mde_unindent_quote", "context": + [ + { "key": "selector", "operator": "equal", "operand": "text.html.markdown", "match_all": true }, + { "key": "preceding_text", "operator": "regex_contains", "operand": "(> )+", "match_all": true } + ] + }, + + // + // References + // + + // Surround with <> on URLs, regex copied from https://mathiasbynens.be/demo/url-regex, @diegoperini (502 chars) + { "keys": ["<"], "command": "insert_snippet", "args": {"contents": "<${0:$SELECTION}>"}, "context": + [ + { "key": "selector", "operator": "equal", "operand": "text.html.markdown - meta.frontmatter - meta.disable-markdown - markup.raw - markup.kbd", "match_all": true }, + { "key": "setting.auto_match_enabled", "operator": "equal", "operand": true }, + { "key": "selection_empty", "operator": "equal", "operand": false, "match_all": true }, + { "key": "text", "operator": "regex_match", "operand": "(?:(?:https?|ftp)://)(?:\\S+(?::\\S*)?@)?(?:(?!10(?:\\.\\d{1,3}){3})(?!127(?:\\.\\d{1,3}){3})(?!169\\.254(?:\\.\\d{1,3}){2})(?!192\\.168(?:\\.\\d{1,3}){2})(?!172\\.(?:1[6-9]|2\\d|3[0-1])(?:\\.\\d{1,3}){2})(?:[1-9]\\d?|1\\d\\d|2[01]\\d|22[0-3])(?:\\.(?:1?\\d{1,2}|2[0-4]\\d|25[0-5])){2}(?:\\.(?:[1-9]\\d?|1\\d\\d|2[0-4]\\d|25[0-4]))|(?:(?:[a-z\\x{00a1}-\\x{ffff}0-9]+-?)*[a-z\\x{00a1}-\\x{ffff}0-9]+)(?:\\.(?:[a-z\\x{00a1}-\\x{ffff}0-9]+-?)*[a-z\\x{00a1}-\\x{ffff}0-9]+)*(?:\\.(?:[a-z\\x{00a1}-\\x{ffff}]{2,})))(?::\\d{2,5})?(?:/[^\\s]*)?", "match_all": true } + ] + }, + // modify [] pairing so that selection is removed after pairing, ready for [] or () + { "keys": ["["], "command": "insert_snippet", "args": {"contents": "[$SELECTION]$0"}, "context": + [ + { "key": "selector", "operator": "equal", "operand": "text.html.markdown - meta.frontmatter - meta.disable-markdown - markup.raw - markup.kbd", "match_all": true }, + { "key": "setting.auto_match_enabled", "operator": "equal", "operand": true }, + { "key": "selection_empty", "operator": "equal", "operand": false, "match_all": true } + ] + }, + // inline image insertion + { "keys": ["ctrl+shift+k"], "command": "mde_reference_new_inline_image", "context": + [ + { "key": "selector", "operator": "equal", "operand": "text.html.markdown", "match_all": true }, + { "key": "setting.mde.keymap_disable.reference_new_inline_image", "operator": "not_equal", "operand": true } + ] + }, + // run paste as link command on selected text + { "keys": ["ctrl+alt+v"], "command": "mde_reference_new_inline_link", "context": + [ + { "key": "selector", "operator": "equal", "operand": "text.html.markdown", "match_all": true }, + { "key": "setting.mde.keymap_disable.reference_new_inline_link", "operator": "not_equal", "operand": true } + ] + }, + // create new footnote + { "keys": ["alt+shift+6"], "command": "mde_reference_new_footnote", "context": + [ + { "key": "selector", "operator": "equal", "operand": "text.html.markdown", "match_all": true }, + { "key": "setting.mde.keymap_disable.reference_new_footnote", "operator": "not_equal", "operand": true } + ] + }, + // create new reference + { "keys": ["ctrl+alt+r"], "command": "mde_reference_new_reference", "context": + [ + { "key": "selector", "operator": "equal", "operand": "text.html.markdown", "match_all": true }, + { "key": "setting.mde.keymap_disable.reference_new_reference", "operator": "not_equal", "operand": true } + ] + }, + // extend numbered reference if auto completion panel is not visible + { "keys": ["enter"], "command": "mde_add_numbered_reference_definition", "context": + [ + { "key": "selector", "operator": "equal", "operand": "text.html.markdown - meta.frontmatter - meta.disable-markdown - markup.raw", "match_all": true }, + { "key": "preceding_text", "operator": "regex_contains", "operand": "^\\s*\\[.*\\d+\\]:", "match_all": true }, + { "key": "auto_complete_visible", "operand": false } + ] + }, + // extend numbered reference if auto-completions are commited via tab only + { "keys": ["enter"], "command": "mde_add_numbered_reference_definition", "context": + [ + { "key": "selector", "operator": "equal", "operand": "text.html.markdown - meta.frontmatter - meta.disable-markdown - markup.raw", "match_all": true }, + { "key": "preceding_text", "operator": "regex_contains", "operand": "^\\s*\\[.*\\d+\\]:", "match_all": true }, + { "key": "setting.auto_complete_commit_on_tab" } + ] + }, + // jump to reference + { "keys": ["ctrl+alt+g"], "command": "mde_reference_jump", "context": + [ + { "key": "selector", "operator": "equal", "operand": "text.html.markdown", "match_all": true }, + { "key": "setting.mde.keymap_disable.reference_jump", "operator": "not_equal", "operand": true } + ] + }, + // organize references + { "keys": ["ctrl+alt+s"], "command": "mde_reference_organize", "context": + [ + { "key": "selector", "operator": "equal", "operand": "text.html.markdown", "match_all": true }, + { "key": "setting.mde.keymap_disable.reference_organize", "operator": "not_equal", "operand": true } + ] + }, + + // + // CriticMarkup + // + + // insert new addition or mark selection for addition + { "keys": ["alt+c", "alt+a"], "command": "insert_snippet", "args": {"name": "Packages/MarkdownEditing/snippets/Critic Addition.sublime-snippet"}, "context": + [ + { "key": "selector", "operator": "equal", "operand": "text.html.markdown - meta.frontmatter - meta.disable-markdown - markup.critic - meta.code-fence - markup.raw - markup.kbd", "match_all": true } + ] + }, + // commit addition + { "keys": ["alt+enter"], "command": "run_macro_file", "args": {"file": "Packages/MarkdownEditing/macros/Commit Critic Addition.sublime-macro"}, "context": + [ + { "key": "selector", "operator": "equal", "operand": "text.html.markdown markup.critic.addition", "match_all": true }, + { "key": "selection_empty", "operator": "equal", "operand": true, "match_all": false } + ] + }, + // discard addition + { "keys": ["alt+backspace"], "command": "run_macro_file", "args": {"file": "Packages/MarkdownEditing/macros/Discard Critic Addition.sublime-macro"}, "context": + [ + { "key": "selector", "operator": "equal", "operand": "text.html.markdown markup.critic.addition", "match_all": true }, + { "key": "selection_empty", "operator": "equal", "operand": true, "match_all": false } + ] + }, + + // insert comment or convert selection into comment + { "keys": ["alt+c", "alt+c"], "command": "insert_snippet", "args": {"name": "Packages/MarkdownEditing/snippets/Critic Comment.sublime-snippet"}, "context": + [ + { "key": "selector", "operator": "equal", "operand": "text.html.markdown - meta.frontmatter - meta.disable-markdown - markup.critic - meta.code-fence - markup.raw - markup.kbd", "match_all": true } + ] + }, + // remove comment + { "keys": ["alt+c", "alt+c"], "command": "run_macro_file", "args": {"file": "Packages/MarkdownEditing/macros/Discard Critic Comment.sublime-macro"}, "context": + [ + { "key": "selector", "operator": "equal", "operand": "text.html.markdown markup.critic.comment", "match_all": true }, + { "key": "selection_empty", "operator": "equal", "operand": true, "match_all": false } + ] + }, + { "keys": ["alt+enter"], "command": "run_macro_file", "args": {"file": "Packages/MarkdownEditing/macros/Discard Critic Comment.sublime-macro"}, "context": + [ + { "key": "selector", "operator": "equal", "operand": "text.html.markdown markup.critic.comment", "match_all": true }, + { "key": "selection_empty", "operator": "equal", "operand": true, "match_all": false } + ] + }, + { "keys": ["alt+backspace"], "command": "run_macro_file", "args": {"file": "Packages/MarkdownEditing/macros/Discard Critic Comment.sublime-macro"}, "context": + [ + { "key": "selector", "operator": "equal", "operand": "text.html.markdown markup.critic.comment", "match_all": true }, + { "key": "selection_empty", "operator": "equal", "operand": true, "match_all": false } + ] + }, + + // mark word for deletion + { "keys": ["alt+c", "alt+d"], "command": "run_macro_file", "args": {"file": "Packages/MarkdownEditing/macros/Transform Word - Critic Deletion.sublime-macro"}, "context": + [ + { "key": "selector", "operator": "equal", "operand": "text.html.markdown - meta.frontmatter - meta.disable-markdown - markup.critic - meta.code-fence - markup.raw - markup.kbd", "match_all": true }, + { "key": "selection_empty", "operator": "equal", "operand": true, "match_all": false } + ] + }, + // mark selection for deletion + { "keys": ["alt+c", "alt+d"], "command": "insert_snippet", "args": {"name": "Packages/MarkdownEditing/snippets/Critic Deletion.sublime-snippet"}, "context": + [ + { "key": "selector", "operator": "equal", "operand": "text.html.markdown - meta.frontmatter - meta.disable-markdown - markup.critic - meta.code-fence - markup.raw - markup.kbd", "match_all": true }, + { "key": "selection_empty", "operator": "equal", "operand": false, "match_all": true } + ] + }, + // commit deletion + { "keys": ["alt+enter"], "command": "run_macro_file", "args": {"file": "Packages/MarkdownEditing/macros/Commit Critic Deletion.sublime-macro"}, "context": + [ + { "key": "selector", "operator": "equal", "operand": "text.html.markdown markup.critic.deletion", "match_all": true }, + { "key": "selection_empty", "operator": "equal", "operand": true, "match_all": false } + ] + }, + // discard deletion + { "keys": ["alt+backspace"], "command": "run_macro_file", "args": {"file": "Packages/MarkdownEditing/macros/Discard Critic Deletion.sublime-macro"}, "context": + [ + { "key": "selector", "operator": "equal", "operand": "text.html.markdown markup.critic.deletion", "match_all": true }, + { "key": "selection_empty", "operator": "equal", "operand": true, "match_all": false } + ] + }, + + // mark word for highlight + { "keys": ["alt+c", "alt+h"], "command": "run_macro_file", "args": {"file": "Packages/MarkdownEditing/macros/Transform Word - Critic Highlight.sublime-macro"}, "context": + [ + { "key": "selector", "operator": "equal", "operand": "text.html.markdown - meta.frontmatter - meta.disable-markdown - markup.critic - meta.code-fence - markup.raw - markup.kbd", "match_all": true }, + { "key": "selection_empty", "operator": "equal", "operand": true, "match_all": false } + ] + }, + // mark selection for highlighting + { "keys": ["alt+c", "alt+h"], "command": "insert_snippet", "args": {"name": "Packages/MarkdownEditing/snippets/Critic Highlight.sublime-snippet"}, "context": + [ + { "key": "selector", "operator": "equal", "operand": "text.html.markdown - meta.frontmatter - meta.disable-markdown - markup.critic - meta.code-fence - markup.raw - markup.kbd", "match_all": true }, + { "key": "selection_empty", "operator": "equal", "operand": false, "match_all": true } + ] + }, + // remove highlight + { "keys": ["alt+enter"], "command": "run_macro_file", "args": {"file": "Packages/MarkdownEditing/macros/Discard Critic Highlight.sublime-macro"}, "context": + [ + { "key": "selector", "operator": "equal", "operand": "text.html.markdown markup.critic.highlight", "match_all": true }, + { "key": "selection_empty", "operator": "equal", "operand": true, "match_all": false } + ] + }, + { "keys": ["alt+backspace"], "command": "run_macro_file", "args": {"file": "Packages/MarkdownEditing/macros/Discard Critic Highlight.sublime-macro"}, "context": + [ + { "key": "selector", "operator": "equal", "operand": "text.html.markdown markup.critic.highlight", "match_all": true }, + { "key": "selection_empty", "operator": "equal", "operand": true, "match_all": false } + ] + }, + + // mark word for substitution + { "keys": ["alt+c", "alt+s"], "command": "run_macro_file", "args": {"file": "Packages/MarkdownEditing/macros/Transform Word - Critic Substitution.sublime-macro"}, "context": + [ + { "key": "selector", "operator": "equal", "operand": "text.html.markdown - meta.frontmatter - meta.disable-markdown - markup.critic - meta.code-fence - markup.raw - markup.kbd", "match_all": true }, + { "key": "selection_empty", "operator": "equal", "operand": true, "match_all": false } + ] + }, + // mark selection for substitution + { "keys": ["alt+c", "alt+s"], "command": "insert_snippet", "args": {"name": "Packages/MarkdownEditing/snippets/Critic Substitution.sublime-snippet"}, "context": + [ + { "key": "selector", "operator": "equal", "operand": "text.html.markdown - meta.frontmatter - meta.disable-markdown - markup.critic - meta.code-fence - markup.raw - markup.kbd", "match_all": true }, + { "key": "selection_empty", "operator": "equal", "operand": false, "match_all": true } + ] + }, + // commit substitution + { "keys": ["alt+enter"], "command": "run_macro_file", "args": {"file": "Packages/MarkdownEditing/macros/Commit Critic Substitution.sublime-macro"}, "context": + [ + { "key": "selector", "operator": "equal", "operand": "text.html.markdown markup.critic.substitution", "match_all": true }, + { "key": "selection_empty", "operator": "equal", "operand": true, "match_all": false } + ] + }, + // discard substitution + { "keys": ["alt+backspace"], "command": "run_macro_file", "args": {"file": "Packages/MarkdownEditing/macros/Discard Critic Substitution.sublime-macro"}, "context": + [ + { "key": "selector", "operator": "equal", "operand": "text.html.markdown markup.critic.substitution", "match_all": true }, + { "key": "selection_empty", "operator": "equal", "operand": true, "match_all": false } + ] + }, + + // + // Wiki + // + + { "keys": ["ctrl+alt+h"], "command": "mde_open_home_page", "context": + [ + { "key": "selector", "operator": "equal", "operand": "text.html.markdown", "match_all": true }, + { "key": "setting.mde.keymap_disable.open_home_page", "operator": "not_equal", "operand": true } + ] + }, + { "keys": ["ctrl+alt+d"], "command": "mde_open_page", "context": + [ + { "key": "selector", "operator": "equal", "operand": "meta.link.wiki.markdown", "match_all": true }, + { "key": "setting.mde.keymap_disable.open_page", "operator": "not_equal", "operand": true } + ] + }, + { "keys": ["ctrl+alt+d"], "command": "mde_make_page_reference", "context": + [ + { "key": "selector", "operator": "equal", "operand": "text.html.markdown - (meta.link.wiki | markup.underline.link)", "match_all": true }, + { "key": "setting.mde.keymap_disable.make_page_reference", "operator": "not_equal", "operand": true } + ] + }, + { "keys": ["ctrl+alt+x"], "command": "mde_list_back_links", "context": + [ + { "key": "selector", "operator": "equal", "operand": "text.html.markdown", "match_all": true }, + { "key": "setting.mde.keymap_disable.list_back_links", "operator": "not_equal", "operand": true } + ] + }, + { "keys": ["ctrl+alt+j"], "command": "mde_open_journal", "context": + [ + { "key": "selector", "operator": "equal", "operand": "text.html.markdown", "match_all": true }, + { "key": "setting.mde.keymap_disable.open_journal", "operator": "not_equal", "operand": true } + ] + } ] diff --git a/Default.sublime-commands b/Default.sublime-commands index af5a4c29..b71f073d 100644 --- a/Default.sublime-commands +++ b/Default.sublime-commands @@ -1,176 +1,281 @@ [ - { - "caption": "MarkdownEditing: Fix Underlined Headers", - "command": "fix_all_underlined_headers" - }, - { - "caption": "MarkdownEditing: Convert Underlined Headers to ATX", - "command": "convert_to_atx" - }, - { - "caption": "MarkdownEditing: Add Missing Link Labels", - "command": "gather_missing_link_markers" - }, - { - "caption": "Preferences: MarkdownEditing Settings – Default", - "command": "open_file", "args": - { - "file": "${packages}/MarkdownEditing/Markdown.sublime-settings" - } - }, - { - "caption": "Preferences: MarkdownEditing Settings – User", - "command": "open_file", "args": - { - "file": "${packages}/User/Markdown.sublime-settings" - } - }, - { - "caption": "MarkdownEditing: Markdown Lint", - "command": "markdown_lint" - }, - { - "caption": "MarkdownEditing: Switch List Bullet Type", - "command": "switch_list_bullet_type" - }, - { - "caption": "MarkdownEditing: Magic Footnotes Command", - "command": "magic_footnotes" - }, - { - "caption": "MarkdownEditing: Gather Missing Footnotes", - "command": "gather_missing_footnotes" - }, - { - "caption": "MarkdownEditing: Jump Reference", - "command": "reference_jump" - }, - { - "caption": "MarkdownEditing: New Reference", - "command": "reference_new_reference" - }, - { - "caption": "MarkdownEditing: New Inline Link", - "command": "reference_new_inline_link" - }, - { - "caption": "MarkdownEditing: New Inline Image", - "command": "reference_new_inline_image" - }, - { - "caption": "MarkdownEditing: New Image", - "command": "reference_new_image" - }, - { - "caption": "MarkdownEditing: New Footnote", - "command": "reference_new_footnote" - }, - { - "caption": "MarkdownEditing: Delete Reference", - "command": "reference_delete_reference" - }, - { - "caption": "MarkdownEditing: Organize References", - "command": "reference_organize" - }, - { - "caption": "MarkdownEditing: Toggle Folding Current Section", - "command": "fold_section" - }, - { - "caption": "MarkdownEditing: Fold Level 1 Sections", - "command": "fold_all_sections", "args" : - { - "target_level" : 1 - } - }, - { - "caption": "MarkdownEditing: Fold Level 2 Sections", - "command": "fold_all_sections", "args" : - { - "target_level" : 2 - } - }, - { - "caption": "MarkdownEditing: Fold Level 3 Sections", - "command": "fold_all_sections", "args" : - { - "target_level" : 3 - } - }, - { - "caption": "MarkdownEditing: Fold Level 4 Sections", - "command": "fold_all_sections", "args" : - { - "target_level" : 4 - } - }, - { - "caption": "MarkdownEditing: Fold All Sections", - "command": "fold_all_sections" - }, - { - "caption": "MarkdownEditing: Unfold All Sections", - "command": "unfold_all_sections" - }, - { - "caption": "MarkdownEditing: Find Next Heading (Same or higher level)", - "command": "goto_next_heading", "args" : - { - "same_level" : true - } - }, - { - "caption": "MarkdownEditing: Find Next Heading (Any level)", - "command": "goto_next_heading", "args" : - { - "same_level" : false - } - }, - { - "caption": "MarkdownEditing: Find Previous Heading (Same or higher level)", - "command": "goto_previous_heading", "args" : - { - "same_level" : true - } - }, - { - "caption": "MarkdownEditing: Find Previous Heading (Any level)", - "command": "goto_previous_heading", "args" : - { - "same_level" : false - } - }, - { - "caption": "MarkdownEditing: Change color scheme...", - "command": "mde_color_activate" - }, - { - "caption": "MarkdownEditing: Convert all inline links to references", - "command": "convert_inline_links_to_references" - }, - { - "caption": "MarkdownEditing: Convert inline link to reference", - "command": "convert_inline_link_to_reference" - }, - { - "caption": "MarkdownEditing: Open Home Page", - "command": "open_home_page" - }, - { - "caption": "MarkdownEditing: Open Page", - "command": "open_page" - }, - { - "caption": "MarkdownEditing: List Back Links", - "command": "list_back_links" - }, - { - "caption": "MarkdownEditing: Open Journal", - "command": "open_journal" - }, - { - "caption": "MarkdownEditing: Run markdownlint", - "command": "markdown_lint_mdl" - } + // + // Settings + // + + { + "caption": "Preferences: MarkdownEditing Settings", + "command": "edit_settings", + "args": { + "base_file": "${packages}/MarkdownEditing/Preferences.sublime-settings", + "default": "// Settings in here override those in \"Default/Preferences.sublime-settings\",\n// and are overridden in turn by syntax-specific settings.\n{\n\t$0\n}\n" + } + }, + { + "caption": "Preferences: MarkdownEditing Settings - Distraction Free", + "command": "edit_settings", + "args": { + "base_file": "${packages}/MarkdownEditing/Distraction Free.sublime-settings", + "default": "// Settings in here override those in \"Default/Distraction Free.sublime-settings\",\n// and are overridden in turn by syntax-specific settings.\n{\n\t$0\n}\n" + } + }, + { + "caption": "Preferences: MarkdownEditing Key Bindings", + "command": "edit_settings", + "args": { + "base_file": "${packages}/MarkdownEditing/Default (${platform}).sublime-keymap", + "default": "// Bindings in here override those in \"Default/Default.sublime-keymap\"\n[\n\t$0\n]\n" + } + }, + { + "caption": "MarkdownEditing: Select Color scheme", + "command": "mde_select_color_scheme" + }, + { + "caption": "MarkdownEditing: Toggle Centered Line", + "command": "mde_toggle_centered_line" + }, + + // + // Linting + // + + { + "caption": "MarkdownEditing: Markdown Lint", + "command": "mde_markdown_lint" + }, + { + "caption": "MarkdownEditing: Run markdownlint", + "command": "mde_markdown_lint_mdl" + }, + + // + // Headings + // + + { + "caption": "MarkdownEditing: Add Closing Heading Hashes", + "command": "mde_match_heading_hashes", + "args": { "enabled": true } + }, + { + "caption": "MarkdownEditing: Remove Closing Heading Hashes", + "command": "mde_match_heading_hashes", + "args": { "enabled": false } + }, + { + "caption": "MarkdownEditing: Fix Closing Heading Hashes", + "command": "mde_match_heading_hashes" + }, + { + "caption": "MarkdownEditing: Fix Underlined Headings", + "command": "mde_fix_underlined_headings" + }, + { + "caption": "MarkdownEditing: Convert Underlined Headings to ATX", + "command": "mde_convert_underlined_headings_to_atx" + }, + { + "caption": "MarkdownEditing: Convert Heading to Text", + "command": "mde_change_headings_level", + "args": { "to": 0 } + }, + { + "caption": "MarkdownEditing: Set Headings Level 1", + "command": "mde_change_headings_level", + "args": { "to": 1 } + }, + { + "caption": "MarkdownEditing: Set Headings Level 2", + "command": "mde_change_headings_level", + "args": { "to": 2 } + }, + { + "caption": "MarkdownEditing: Set Headings Level 3", + "command": "mde_change_headings_level", + "args": { "to": 3 } + }, + { + "caption": "MarkdownEditing: Set Headings Level 4", + "command": "mde_change_headings_level", + "args": { "to": 4 } + }, + { + "caption": "MarkdownEditing: Set Headings Level 5", + "command": "mde_change_headings_level", + "args": { "to": 5 } + }, + { + "caption": "MarkdownEditing: Set Headings Level 6", + "command": "mde_change_headings_level", + "args": { "to": 6 } + }, + { + "caption": "MarkdownEditing: Increase Headings Level", + "command": "mde_change_headings_level", + "args": { "by": 1 } + }, + { + "caption": "MarkdownEditing: Decrease Headings Level", + "command": "mde_change_headings_level", + "args": { "by": -1 } + }, + { + "caption": "MarkdownEditing: Goto Next Heading (same or higher level)", + "command": "mde_goto_next_heading", + "args": { "same_level": true } + }, + { + "caption": "MarkdownEditing: Goto Next Heading (any level)", + "command": "mde_goto_next_heading", + "args": { "same_level": false } + }, + { + "caption": "MarkdownEditing: Goto Previous Heading (same or higher level)", + "command": "mde_goto_previous_heading", + "args": { "same_level": true } + }, + { + "caption": "MarkdownEditing: Goto Previous Heading (any level)", + "command": "mde_goto_previous_heading", + "args": { "same_level": false } + }, + + // + // Folding + // + + { + "caption": "MarkdownEditing: Toggle Folding Current Section", + "command": "mde_fold_section" + }, + { + "caption": "MarkdownEditing: Fold Level 1 Sections", + "command": "mde_fold_all_sections", + "args": { "target_level": 1 } + }, + { + "caption": "MarkdownEditing: Fold Level 2 Sections", + "command": "mde_fold_all_sections", + "args": { "target_level": 2 } + }, + { + "caption": "MarkdownEditing: Fold Level 3 Sections", + "command": "mde_fold_all_sections", + "args": { "target_level": 3 } + }, + { + "caption": "MarkdownEditing: Fold Level 4 Sections", + "command": "mde_fold_all_sections", + "args": { "target_level": 4 } + }, + { + "caption": "MarkdownEditing: Fold Level 5 Sections", + "command": "mde_fold_all_sections", + "args": { "target_level": 5 } + }, + { + "caption": "MarkdownEditing: Fold Level 6 Sections", + "command": "mde_fold_all_sections", + "args": { "target_level": 6 } + }, + { + "caption": "MarkdownEditing: Fold All Sections", + "command": "mde_fold_all_sections" + }, + { + "caption": "MarkdownEditing: Unfold All Sections", + "command": "mde_unfold_all_sections" + }, + { + "caption": "MarkdownEditing: Auto Fold Link URLs", + "command": "mde_fold_links" + }, + + // + // Lists + // + + { + "caption": "MarkdownEditing: Switch List Bullet Type", + "command": "mde_switch_list_bullet_type" + }, + + // + // References + // + + { + "caption": "MarkdownEditing: Magic Footnotes", + "command": "mde_magic_footnotes" + }, + { + "caption": "MarkdownEditing: Jump Reference", + "command": "mde_reference_jump" + }, + { + "caption": "MarkdownEditing: New Reference", + "command": "mde_reference_new_reference" + }, + { + "caption": "MarkdownEditing: New Inline Link", + "command": "mde_reference_new_inline_link" + }, + { + "caption": "MarkdownEditing: New Inline Image", + "command": "mde_reference_new_inline_image" + }, + { + "caption": "MarkdownEditing: New Image", + "command": "mde_reference_new_image" + }, + { + "caption": "MarkdownEditing: New Footnote", + "command": "mde_reference_new_footnote" + }, + { + "caption": "MarkdownEditing: Delete Reference", + "command": "mde_reference_delete_reference" + }, + { + "caption": "MarkdownEditing: Convert all inline links to references", + "command": "mde_convert_inline_links_to_references" + }, + { + "caption": "MarkdownEditing: Convert inline link to reference", + "command": "mde_convert_inline_link_to_reference" + }, + { + "caption": "MarkdownEditing: Add Missing Link Labels", + "command": "mde_gather_missing_link_markers" + }, + { + "caption": "MarkdownEditing: Gather Missing Footnotes", + "command": "mde_gather_missing_footnotes" + }, + { + "caption": "MarkdownEditing: Organize References", + "command": "mde_reference_organize" + }, + + // + // Wiki + // + + { + "caption": "MarkdownEditing: Open Home Page", + "command": "mde_open_home_page" + }, + { + "caption": "MarkdownEditing: Open Page", + "command": "mde_open_page" + }, + { + "caption": "MarkdownEditing: Open Journal", + "command": "mde_open_journal" + }, + { + "caption": "MarkdownEditing: List Back Links", + "command": "mde_list_back_links" + } ] diff --git a/Distraction Free.sublime-settings b/Distraction Free.sublime-settings new file mode 100644 index 00000000..37031767 --- /dev/null +++ b/Distraction Free.sublime-settings @@ -0,0 +1,5 @@ +{ + // MarkdownEditing: + // Always keep current line vertically centered. + "mde.keep_centered": true +} diff --git a/Main.sublime-menu b/Main.sublime-menu index ba27d0e6..0ab42e50 100644 --- a/Main.sublime-menu +++ b/Main.sublime-menu @@ -1,154 +1,56 @@ [ - { - "caption": "Preferences", - "children": [ - { - "caption": "Package Settings", - "children": [ - { - "caption": "Markdown Editing", - "children": [ - { - "args": { - "file": "${packages}/MarkdownEditing/README.md" - }, - "caption": "README", - "command": "open_file" - }, - { - "caption": "Change color scheme...", - "command": "mde_color_activate" - }, - { - "caption": "-" - }, - { - "args": { - "file": "${packages}/MarkdownEditing/Bold and Italic Markers.tmPreferences" - }, - "caption": "Bold and Italic Settings \u2013 Default", - "command": "open_file" - }, - { - "args": { - "file": "${packages}/User/Bold and Italic Markers.tmPreferences" - }, - "caption": "Bold and Italic Settings \u2013 User", - "command": "open_file" - }, - { - "caption": "-" - }, - { - "args": { - "file": "${packages}/MarkdownEditing/Markdown.sublime-settings" - }, - "caption": "Markdown GFM Settings \u2013 Default", - "command": "open_file" - }, - { - "args": { - "file": "${packages}/User/Markdown.sublime-settings" - }, - "caption": "Markdown GFM Settings \u2013 User", - "command": "open_file" - }, - { - "caption": "-" - }, - { - "args": { - "file": "${packages}/MarkdownEditing/Markdown (Standard).sublime-settings" - }, - "caption": "Markdown (Standard) Settings \u2013 Default", - "command": "open_file" - }, - { - "args": { - "file": "${packages}/User/Markdown (Standard).sublime-settings" - }, - "caption": "Markdown (Standard) Settings \u2013 User", - "command": "open_file" - }, - { - "caption": "-" - }, - { - "args": { - "file": "${packages}/MarkdownEditing/MultiMarkdown.sublime-settings" - }, - "caption": "MultiMarkdown Settings \u2013 Default", - "command": "open_file" - }, - { - "args": { - "file": "${packages}/User/MultiMarkdown.sublime-settings" - }, - "caption": "MultiMarkdown Settings \u2013 User", - "command": "open_file" - }, - { - "caption": "-" - }, - { - "args": { - "file": "${packages}/MarkdownEditing/Default (Windows).sublime-keymap", - "platform": "Windows" - }, - "caption": "Key Bindings \u2013 Default", - "command": "open_file" - }, - { - "args": { - "file": "${packages}/MarkdownEditing/Default (OSX).sublime-keymap", - "platform": "OSX" - }, - "caption": "Key Bindings \u2013 Default", - "command": "open_file" - }, - { - "args": { - "file": "${packages}/MarkdownEditing/Default (Linux).sublime-keymap", - "platform": "Linux" - }, - "caption": "Key Bindings \u2013 Default", - "command": "open_file" - }, - { - "args": { - "file": "${packages}/User/Default (Windows).sublime-keymap", - "platform": "Windows" - }, - "caption": "Key Bindings \u2013 User", - "command": "open_file" - }, - { - "args": { - "file": "${packages}/User/Default (OSX).sublime-keymap", - "platform": "OSX" - }, - "caption": "Key Bindings \u2013 User", - "command": "open_file" - }, - { - "args": { - "file": "${packages}/User/Default (Linux).sublime-keymap", - "platform": "Linux" - }, - "caption": "Key Bindings \u2013 User", - "command": "open_file" - }, - { - "caption": "-" - } - ] - } - ], - "id": "package-settings", - "mnemonic": "P" - } - ], - "id": "preferences", - "mnemonic": "n" - } -] \ No newline at end of file + { + "caption": "Preferences", + "children": [ + { + "caption": "Package Settings", + "children": [ + { + "caption": "Markdown Editing", + "children": [ + { + "caption": "README", + "command": "open_file", + "args": { + "file": "${packages}/MarkdownEditing/README.md" + } + }, + { + "caption": "Select Color Scheme", + "command": "mde_select_color_scheme" + }, + { + "caption": "Settings", + "command": "edit_settings", + "args": { + "base_file": "${packages}/MarkdownEditing/Preferences.sublime-settings", + "default": "// Settings in here override those in \"Default/Preferences.sublime-settings\",\n// and are overridden in turn by syntax-specific settings.\n{\n\t$0\n}\n" + } + }, + { + "caption": "Settings - Distraction Free", + "command": "edit_settings", + "args": { + "base_file": "${packages}/MarkdownEditing/Distraction Free.sublime-settings", + "default": "// Settings in here override those in \"Default/Distraction Free.sublime-settings\",\n// and are overridden in turn by syntax-specific settings.\n{\n\t$0\n}\n" + } + }, + { + "caption": "Key Bindings", + "command": "edit_settings", + "args": { + "base_file": "${packages}/MarkdownEditing/Default (${platform}).sublime-keymap", + "default": "// Bindings in here override those in \"Default/Default.sublime-keymap\"\n[\n\t$0\n]\n" + } + } + ] + } + ], + "id": "package-settings", + "mnemonic": "P" + } + ], + "id": "preferences", + "mnemonic": "n" + } +] diff --git a/Markdown (Standard).sublime-settings b/Markdown (Standard).sublime-settings deleted file mode 100644 index 43ec11a8..00000000 --- a/Markdown (Standard).sublime-settings +++ /dev/null @@ -1,148 +0,0 @@ -{ - "color_scheme": "Packages/MarkdownEditing/MarkdownEditor.tmTheme", - // "color_scheme": "Packages/MarkdownEditing/MarkdownEditor-Dark.tmTheme", - // "color_scheme": "Packages/MarkdownEditing/MarkdownEditor-Yellow.tmTheme", - - // This is a quick and dirty focus theme. In order to make it work, you've to - // set `"highlight_line": true,` in this settings file. It is likely that there will - // be more mature focus improvements in the future (maybe similar to iA Writer). - // "color_scheme": "Packages/MarkdownEditing/MarkdownEditor-Focus.tmTheme", - - "tab_size": 4, - "translate_tabs_to_spaces": true, - "trim_trailing_white_space_on_save": false, - "auto_match_enabled": true, - - // Layout - "draw_centered": true, - "word_wrap": true, - "wrap_width": 80, - "rulers": [], - - // Line - "line_numbers": false, - "highlight_line": false, - "line_padding_top": 2, - "line_padding_bottom": 2, - - // Caret - "caret_style": "wide", - "caret_extra_top": 3, - "caret_extra_bottom": 3, - - // add trailing #'s to headlines - "mde.match_header_hashes": false, - - // Automatically switches list bullet when indenting blank list item with . - "mde.list_indent_auto_switch_bullet": true, - - // List bullets to be used for automatically switching. In their order. - "mde.list_indent_bullets": ["*", "-", "+"], - - // Auto increments ordered list number. Set to false if you want always "1". - "mde.auto_increment_ordered_list_number": true, - - // Always keep current line vertically centered. - "mde.keep_centered": false, - - // Distraction free mode improvements. In order for these to work, you have to install - // FullScreenStatus plugin: https://github.com/maliayas/SublimeText_FullScreenStatus - "mde.distraction_free_mode": { - "mde.keep_centered": true - }, - - "mde.lint":{ - "mdl": { - // By default it is mdl.bat on windows and mdl otherwise. Leave it blank to use the default value - // If you are using a custom launcher, you may want to change this - "executable": "", - // Extra arguments passed to mdl. For all options, see here: - // https://github.com/markdownlint/markdownlint/blob/master/lib/mdl/cli.rb - // You can also specify a config file with '-c ~/.mdlrc' - "additional_arguments": [] - }, - // disabled rules, e.g. "md001". - "disable": ["md013"], - // Options: - // atx, ## title only - // atx_closed, ## title ## only - // setext, title only - // ===== - // any, consistent within the document - "md003": "any", - // Options: - // asterisk, * only - // plus, + only - // dash, - only - // cyclic, different symbols on different levels - // and same symbol on same level - // single, same symbol on different levels - // any, same symbol on same level - "md004": "cyclic", - // Number of spaces per list indent. Set to 0 to use Sublime tab_size instead - "md007": 0, - // Maximum line length, Set to 0 to use Sublime wrap_width instead - "md013": 0, - // Disallowed trailing punctuation in headers - "md026": ".,;:!", - // Options: - // one, '1.' only - // ordered, ascending number - // any, consistent within one list - "md029": "any", - // (ordered vs unordered, single-line vs multi-line) - "md030": { - "ul_single": 1, - "ol_single": 1, - // optinally, 3 - "ul_multi": 1, - // optionaly, 2 - "ol_multi": 1 - } - }, - - "mde.wikilinks.markdown_extension": ".md", - "mde.wikilinks.homepage": "HomePage", - "mde.wikilinks.templates": { - "default_page": "templates/PageTemplate.md" - }, - - // You can opt out some keybinds by setting the corresponding value from 'false' to 'true' (without single-quotes). - // Super key references to a key next to left Alt key. It usually has a Windows logo or "win" or "Command" on it. - // Jump between link/image/footnote reference and definition - // Default keys: (OSX)super+ctrl+shift+l (Linux/Win)ctrl+alt+g - "mde.keymap_disable.reference_jump": false, - // Add a new link - // Default keys: (OSX)super+alt+r (Linux/Win)ctrl+super+r - "mde.keymap_disable.reference_new_reference": false, - // Add a new inline link - // Default keys: (OSX)super+alt+v (Linux/Win)ctrl+super+v - "mde.keymap_disable.reference_new_inline_link": false, - // Add a new inline image - // Default keys: (OSX/Linux/Win)super+shift+k - "mde.keymap_disable.reference_new_inline_image": false, - // Add a new footnote - // Default keys: (OSX/Linux/Win)alt+shift+6 - "mde.keymap_disable.reference_new_footnote": false, - // Fold current section - // Default keys: (OSX/Linux/Win)shift+tab - "mde.keymap_disable.fold_section": false, - // Open a panel showing all functions related to folding - // Default keys: (OSX/Linux/Win)ctrl+shift+tab - "mde.keymap_disable.show_fold_all_sections": false, - // Jump to the next heading (any level/same or higher level) - // Default keys: (OSX)super+ctrl/shift+pagedown (Linux/Win)ctrl+shift(+alt)+pagedown - "mde.keymap_disable.goto_next_heading": false, - // Jump to the previous heading (any level/same or higher level) - // Default keys: (OSX)super+ctrl/shift+pageup (Linux/Win)ctrl+shift(+alt)+pageup - "mde.keymap_disable.goto_previous_heading": false, - // List pages the link to the current page - "mde.keymap_disable.list_back_links": true, - // Open the home page - "mde.keymap_disable.open_home_page": true, - // Open the journal - "mde.keymap_disable.open_journal": true, - // Open the page referenced - "mde.keymap_disable.open_page": true, - // Make page reference -} diff --git a/Markdown (Standard).tmLanguage b/Markdown (Standard).tmLanguage deleted file mode 100644 index 4404d611..00000000 --- a/Markdown (Standard).tmLanguage +++ /dev/null @@ -1,1426 +0,0 @@ - - - - - fileTypes - - md - mdown - markdown - markdn - - foldingStartMarker - (?x) - (<(?i:head|body|table|thead|tbody|tfoot|tr|div|select|fieldset|style|script|ul|ol|form|dl)\b.*?> - |<!--(?!.*-->) - |\{\s*($|\?>\s*$|//|/\*(.*\*/\s*$|(?!.*?\*/))) - ) - foldingStopMarker - (?x) - (</(?i:head|body|table|thead|tbody|tfoot|tr|div|select|fieldset|style|script|ul|ol|form|dl)> - |^\s*--> - |(^|\s)\} - ) - keyEquivalent - ^~M - name - Markdown - patterns - - - begin - (?x)^ - (?= [ ]{,3}> - | ([ ]{4}|\t)(?!$) - | [#]{1,6}\s*+ - | [ ]{,3}(?<marker>[-*_])([ ]{,2}\k<marker>){2,}[ \t]*+$ - ) - comment - - We could also use an empty end match and set - applyEndPatternLast, but then we must be sure that the begin - pattern will only match stuff matched by the sub-patterns. - - end - (?x)^ - (?! [ ]{,3}> - | ([ ]{4}|\t) - | [#]{1,6}\s*+ - | [ ]{,3}(?<marker>[-*_])([ ]{,2}\k<marker>){2,}[ \t]*+$ - ) - name - meta.block-level.markdown - patterns - - - include - #block_quote - - - include - #block_raw - - - include - #heading - - - include - #separator - - - - - begin - ^[ ]{0,3}([*+-])(?=\s) - captures - - 1 - - name - punctuation.definition.list_item.markdown - - - end - ^(?=\S) - name - markup.list.unnumbered.markdown - patterns - - - include - #list-paragraph - - - - - begin - ^[ ]{0,3}([0-9]+)(\.)(?=\s) - captures - - 1 - - name - punctuation.definition.list_item.markdown punctuation.definition.list_item.number.markdown - - 2 - - name - punctuation.definition.list_item.markdown - - - end - ^(?=\S) - name - markup.list.numbered.markdown - patterns - - - include - #list-paragraph - - - - - begin - ^(?=<(p|div|h[1-6]|blockquote|pre|table|dl|ol|ul|script|noscript|form|fieldset|iframe|math|ins|del)\b[^>]*>)(?!.*?</\1>) - comment - - Markdown formatting is disabled inside block-level tags. - - end - (?<=^</\1>$\n) - patterns - - - include - text.html.basic - - - name - meta.disable-markdown - - - begin - ^(?=<(p|div|h[1-6]|blockquote|pre|table|dl|ol|ul|script|noscript|form|fieldset|iframe|math|ins|del)\b[^>]*>) - comment - Same rule but for one line disables. - end - $\n? - patterns - - - include - text.html.basic - - - name - meta.disable-markdown - - - captures - - 1 - - name - punctuation.definition.constant.begin.markdown - - 2 - - name - constant.other.reference.link.markdown - - 3 - - name - punctuation.definition.constant.end.markdown - - 4 - - name - punctuation.separator.key-value.markdown - - 5 - - name - meta.paragraph.markdown - - - match - (?x: - \s* # Leading whitespace - (\[)(\^\d+?)(\])(:) # Reference name - [ \t]* # Optional whitespace - (.+?) # The footnote - [ \t]* # Optional whitespace - $ - ) - name - meta.link.reference.footnote.markdown - - - captures - - 1 - - name - punctuation.definition.constant.begin.markdown - - 10 - - name - punctuation.definition.string.end.markdown - - 11 - - name - string.other.link.description.title.markdown - - 12 - - name - punctuation.definition.string.begin.markdown - - 13 - - name - punctuation.definition.string.end.markdown - - 2 - - name - constant.other.reference.link.markdown - - 3 - - name - punctuation.definition.constant.end.markdown - - 4 - - name - punctuation.separator.key-value.markdown - - 5 - - name - punctuation.definition.link.markdown - - 6 - - name - markup.underline.link.markdown - - 7 - - name - punctuation.definition.link.markdown - - 8 - - name - string.other.link.description.title.markdown - - 9 - - name - punctuation.definition.string.begin.markdown - - - match - (?x: - \s* # Leading whitespace - (\[)(.+?)(\])(:) # Reference name - [ \t]* # Optional whitespace - (<?)(\S+?)(>?) # The url - [ \t]* # Optional whitespace - (?: - ((\().+?(\))) # Match title in quotes… - | ((").+?(")) # or in parens. - )? # Title is optional - [ \t]* # Optional whitespace - $ - ) - name - meta.link.reference.def.markdown - - - begin - ^(?=\S)(?![=-]{3,}(?=$)) - end - ^(?:\s*$|(?=[ ]{,3}>))|(?=[ \t]*\n)(?<=^===|^====|=====|^---|^----|-----)[ \t]*\n|(?=^#) - name - meta.paragraph.markdown - patterns - - - include - #inline - - - include - text.html.basic - - - captures - - 1 - - name - punctuation.definition.heading.markdown - - - match - ^(={3,})(?=[ \t]*$) - name - markup.heading.1.markdown - - - captures - - 1 - - name - punctuation.definition.heading.markdown - - - match - ^(-{3,})(?=[ \t]*$) - name - markup.heading.2.markdown - - - - - repository - - ampersand - - comment - - Markdown will convert this for us. We match it so that the - HTML grammar will not mark it up as invalid. - - match - &(?!([a-zA-Z0-9]+|#[0-9]+|#x[0-9a-fA-F]+);) - name - meta.other.valid-ampersand.markdown - - block_quote - - begin - \G[ ]{,3}(>)[ ]? - beginCaptures - - 1 - - name - punctuation.definition.blockquote.markdown - - - comment - - We terminate the block quote when seeing an empty line, a - separator or a line with leading > characters. The latter is - to “reset” the quote level for quoted lines. - - end - (?x)^ - (?= \s*$ - | [ ]{,3}(?<marker>[-*_])([ ]{,2}\k<marker>){2,}[ \t]*+$ - | [ ]{,3}> - ) - name - markup.quote.markdown - patterns - - - begin - (?x)\G - (?= [ ]{,3}> - ) - end - ^ - patterns - - - include - #block_quote - - - - - applyEndPatternLast - 1 - begin - (?x)\G - (?= ([ ]{4}|\t) - | [#]{1,6}\s*+ - | [ ]{,3}(?<marker>[-*_])([ ]{,2}\k<marker>){2,}[ \t]*+$ - ) - end - ^ - patterns - - - include - #block_raw - - - include - #heading - - - include - #separator - - - - - begin - (?x)\G - (?! $ - | [ ]{,3}> - | ([ ]{4}|\t) - | [#]{1,6}\s*+ - | [ ]{,3}(?<marker>[-*_])([ ]{,2}\k<marker>){2,}[ \t]*+$ - ) - end - $|(?<=\n) - patterns - - - include - #inline - - - - - - block_raw - - match - \G([ ]{4}|\t).*$\n? - name - markup.raw.block.markdown - - bold_italic - - begin - (?x) - (\*|_)(?=\1\1)(\1\1)(?=\S) # Open - (?= - ( - <[^>]*+> # HTML tags - | (?<raw>`+)([^`]|(?!(?<!`)\k<raw>(?!`))`)*+\k<raw> - # Raw - | \\[\\`*_{}\[\]()#.!+\->]?+ # Escapes - | \[ - ( - (?<square> # Named group - [^\[\]\\] # Match most chars - | \\. # Escaped chars - | \[ \g<square>*+ \] # Nested brackets - )*+ - \] - ( - ( # Reference Link - [ ]? # Optional space - \[[^\]]*+\] # Ref name - ) - | ( # Inline Link - \( # Opening paren - [ \t]*+ # Optional whtiespace - <?(.*?)>? # URL - [ \t]*+ # Optional whtiespace - ( # Optional Title - (?<title>['"]) - (.*?) - \k<title> - )? - \) - ) - ) - ) - | (?!(?<=\S)\1{3}(?!\1)). # Everything besides - # style closer - )++ - (?<=\S)\1{3}(?!\1) # Close - ) - - captures - - 1 - - name - punctuation.definition.bold.markdown - - 2 - - name - punctuation.definition.bold.markdown - - - end - (?<=\S)(\1{3})(?!\1) - name - markup.bold_italic.markdown - patterns - - - applyEndPatternLast - 1 - begin - (?=<[^>]*?>) - end - (?<=>) - patterns - - - include - text.html.basic - - - - - include - #escape - - - include - #ampersand - - - include - #bracket - - - include - #raw - - - include - #image-inline - - - include - #link-inline - - - include - #link-inet - - - include - #link-email - - - include - #link-wiki - - - include - #image-ref - - - include - #link-ref-literal - - - include - #link-ref - - - - bold - - begin - (?x) - (\*\*|__)(?=\S) # Open - (?= - ( - <[^>]*+> # HTML tags - | (?<raw>`+)([^`]|(?!(?<!`)\k<raw>(?!`))`)*+\k<raw> - # Raw - | \\[\\`*_{}\[\]()#.!+\->]?+ # Escapes - | \[ - ( - (?<square> # Named group - [^\[\]\\] # Match most chars - | \\. # Escaped chars - | \[ \g<square>*+ \] # Nested brackets - )*+ - \] - ( - ( # Reference Link - [ ]? # Optional space - \[[^\]]*+\] # Ref name - ) - | ( # Inline Link - \( # Opening paren - [ \t]*+ # Optional whtiespace - <?(.*?)>? # URL - [ \t]*+ # Optional whtiespace - ( # Optional Title - (?<title>['"]) - (.*?) - \k<title> - )? - \) - ) - ) - ) - | (?!(?<=\S)\1). # Everything besides - # style closer - )++ - (?<=\S)\1 # Close - ) - - captures - - 1 - - name - punctuation.definition.bold.markdown - - - end - (?<=\S)(\1) - name - markup.bold.markdown - patterns - - - applyEndPatternLast - 1 - begin - (?=<[^>]*?>) - end - (?<=>) - patterns - - - include - text.html.basic - - - - - include - #escape - - - include - #ampersand - - - include - #bracket - - - include - #raw - - - include - #bold_italic - - - include - #italic - - - include - #image-inline - - - include - #link-inline - - - include - #link-inet - - - include - #link-email - - - include - #link-wiki - - - include - #image-ref - - - include - #link-ref-literal - - - include - #link-ref - - - - bracket - - comment - - Markdown will convert this for us. We match it so that the - HTML grammar will not mark it up as invalid. - - match - <(?![a-z/?\$!]) - name - meta.other.valid-bracket.markdown - - escape - - match - \\[-`*_#+.!(){}\[\]\\>] - name - constant.character.escape.markdown - - heading - - begin - \G(#{1,6})(?!#)\s*(?=\S) - captures - - 1 - - name - punctuation.definition.heading.markdown - - - contentName - entity.name.section.markdown - end - \s*(#*)$\n? - name - markup.heading.markdown - patterns - - - include - #inline - - - - image-inline - - captures - - 1 - - name - punctuation.definition.string.begin.markdown - - 10 - - name - string.other.link.description.title.markdown - - 11 - - name - punctuation.definition.string.markdown - - 12 - - name - punctuation.definition.string.markdown - - 13 - - name - string.other.link.description.title.markdown - - 14 - - name - punctuation.definition.string.markdown - - 15 - - name - punctuation.definition.string.markdown - - 16 - - name - punctuation.definition.metadata.markdown - - 2 - - name - string.other.link.description.markdown - - 4 - - name - punctuation.definition.string.end.markdown - - 5 - - name - invalid.illegal.whitespace.markdown - - 6 - - name - punctuation.definition.metadata.markdown - - 7 - - name - punctuation.definition.link.markdown - - 8 - - name - markup.underline.link.image.markdown - - 9 - - name - punctuation.definition.link.markdown - - - match - (?x: - \! # Images start with ! - (\[)((?<square>[^\[\]\\]|\\.|\[\g<square>*+\])*+)(\]) - # Match the link text. - ([ ])? # Space not allowed - (\() # Opening paren for url - (<?)(\S+?)(>?) # The url - [ \t]* # Optional whitespace - (?: - ((\().+?(\))) # Match title in parens… - | ((").+?(")) # or in quotes. - )? # Title is optional - \s* # Optional whitespace - (\)) - ) - name - meta.image.inline.markdown - - image-ref - - captures - - 1 - - name - punctuation.definition.string.begin.markdown - - 2 - - name - string.other.link.description.markdown - - 4 - - name - punctuation.definition.string.end.markdown - - 5 - - name - punctuation.definition.constant.markdown - - 6 - - name - constant.other.reference.link.markdown - - 7 - - name - punctuation.definition.constant.markdown - - - match - \!(\[)((?<square>[^\[\]\\]|\\.|\[\g<square>*+\])*+)(\])[ ]?(\[)(.*?)(\]) - name - meta.image.reference.markdown - - inline - - patterns - - - include - #escape - - - include - #ampersand - - - include - #bracket - - - include - #raw - - - include - #bold_italic - - - include - #bold - - - include - #italic - - - include - #line-break - - - include - #image-inline - - - include - #link-inline - - - include - #link-inet - - - include - #link-email - - - include - #link-wiki - - - include - #image-ref - - - include - #link-ref-literal - - - include - #link-ref - - - include - text.html.basic - - - - italic - - begin - (?x) - (\*|_)(?=\S) # Open - (?= - ( - <[^>]*+> # HTML tags - | (?<raw>`+)([^`]|(?!(?<!`)\k<raw>(?!`))`)*+\k<raw> - # Raw - | \\[\\`*_{}\[\]()#.!+\->]?+ # Escapes - | \[ - ( - (?<square> # Named group - [^\[\]\\] # Match most chars - | \\. # Escaped chars - | \[ \g<square>*+ \] # Nested brackets - )*+ - \] - ( - ( # Reference Link - [ ]? # Optional space - \[[^\]]*+\] # Ref name - ) - | ( # Inline Link - \( # Opening paren - [ \t]*+ # Optional whtiespace - <?(.*?)>? # URL - [ \t]*+ # Optional whtiespace - ( # Optional Title - (?<title>['"]) - (.*?) - \k<title> - )? - \) - ) - ) - ) - | \1\1 # Must be bold closer - | (?!(?<=\S)\1). # Everything besides - # style closer - )++ - (?<=\S)\1 # Close - ) - - captures - - 1 - - name - punctuation.definition.italic.markdown - - - end - (?<=\S)(\1)((?!\1)|(?=\1\1)) - name - markup.italic.markdown - patterns - - - applyEndPatternLast - 1 - begin - (?=<[^>]*?>) - end - (?<=>) - patterns - - - include - text.html.basic - - - - - include - #escape - - - include - #ampersand - - - include - #bracket - - - include - #raw - - - include - #bold_italic - - - include - #bold - - - include - #image-inline - - - include - #link-inline - - - include - #link-inet - - - include - #link-email - - - include - #link-wiki - - - include - #image-ref - - - include - #link-ref-literal - - - include - #link-ref - - - - line-break - - match - {2,}$ - name - meta.dummy.line-break - - link-email - - captures - - 1 - - name - punctuation.definition.link.markdown - - 2 - - name - markup.underline.link.markdown - - 4 - - name - punctuation.definition.link.markdown - - - match - (<)((?:mailto:)?[-.\w]+@[-a-z0-9]+(\.[-a-z0-9]+)*\.[a-z]+)(>) - name - meta.link.email.lt-gt.markdown - - link-inet - - captures - - 1 - - name - punctuation.definition.link.markdown - - 2 - - name - markup.underline.link.markdown - - 3 - - name - punctuation.definition.link.markdown - - - match - (<)((?:https?|ftp)://.*?)(>) - name - meta.link.inet.markdown - - link-wiki - - captures - - 1 - - name - punctuation.definition.string.begin.markdown - - 2 - - name - markup.underline.link.markdown - - 3 - - name - punctuation.definition.string.end.markdown - - - match - (\[\[)([A-za-z0-9.]+)(\]\]) - name - meta.link.wiki.markdown - - link-inline - - captures - - 1 - - name - punctuation.definition.string.begin.markdown - - 10 - - name - string.other.link.description.title.markdown - - 11 - - name - punctuation.definition.string.begin.markdown - - 12 - - name - punctuation.definition.string.end.markdown - - 13 - - name - string.other.link.description.title.markdown - - 14 - - name - punctuation.definition.string.begin.markdown - - 15 - - name - punctuation.definition.string.end.markdown - - 16 - - name - punctuation.definition.metadata.markdown - - 2 - - name - string.other.link.title.markdown - - 4 - - name - punctuation.definition.string.end.markdown - - 5 - - name - invalid.illegal.whitespace.markdown - - 6 - - name - punctuation.definition.metadata.markdown - - 7 - - name - punctuation.definition.link.markdown - - 8 - - name - markup.underline.link.markdown - - 9 - - name - punctuation.definition.link.markdown - - - match - (?x: - (\[)((?<square>[^\[\]\\]|\\.|\[\g<square>*+\])*+)(\]) - # Match the link text. - ([ ])? # Space not allowed - (\() # Opening paren for url - (<?)(.*?)(>?) # The url - [ \t]* # Optional whitespace - (?: - ((\().+?(\))) # Match title in parens… - | ((").+?(")) # or in quotes. - )? # Title is optional - \s* # Optional whitespace - (\)) - ) - name - meta.link.inline.markdown - - link-ref - - captures - - 1 - - name - punctuation.definition.string.begin.markdown - - 2 - - name - string.other.link.title.markdown - - 4 - - name - punctuation.definition.string.end.markdown - - 5 - - name - punctuation.definition.constant.begin.markdown - - 6 - - name - constant.other.reference.link.markdown - - 7 - - name - punctuation.definition.constant.end.markdown - - - match - (\[)((?<square>[^\[\]\\]|\\.|\[\g<square>*+\])*+)(\])[ ]?(\[)([^\]]*+)(\]) - name - meta.link.reference.markdown - - link-ref-literal - - captures - - 1 - - name - punctuation.definition.string.begin.markdown - - 2 - - name - string.other.link.title.markdown - - 4 - - name - punctuation.definition.string.end.markdown - - 5 - - name - punctuation.definition.constant.begin.markdown - - 6 - - name - punctuation.definition.constant.end.markdown - - - match - (\[)((?<square>[^\[\]\\]|\\.|\[\g<square>*+\])*+)(\])[ ]?(\[)(\]) - name - meta.link.reference.literal.markdown - - list-paragraph - - patterns - - - begin - \G\s+(?=\S) - end - ^\s*$ - name - meta.paragraph.list.markdown - patterns - - - include - #inline - - - match - \G\s*([*\-+]|[0-9]+\.)\s+ - captures - - 1 - - name - punctuation.definition.list_item.markdown - - - - - include - text.html.basic - - - - - - raw - - captures - - 1 - - name - punctuation.definition.raw.markdown - - 2 - - name - markup.raw.inline.content.markdown - - 3 - - name - punctuation.definition.raw.markdown - - - match - (`+)((?:[^`]|(?!(?<!`)\1(?!`))`)*+)(\1) - name - markup.raw.inline.markdown - - separator - - match - \G[ ]{,3}([-*_])([ ]{,2}\1){2,}[ \t]*$\n? - name - meta.separator.markdown - - - scopeName - text.html.markdown - uuid - 075E6FC0-3E42-11E3-AA6E-0800200C9A66 - - diff --git a/Markdown.sublime-syntax b/Markdown.sublime-syntax deleted file mode 100644 index 49da24cb..00000000 --- a/Markdown.sublime-syntax +++ /dev/null @@ -1,983 +0,0 @@ -%YAML 1.2 ---- -# http://www.sublimetext.com/docs/3/syntax.html -name: Markdown GFM -file_extensions: - - md - - mdown - - markdown - - markdn -scope: text.html.markdown.gfm -contexts: - main: - - match: (?=(? - | ([ ]{4}|\t)(?!$) - | [#]{1,6}\s*+ - | [ ]{,3}(?[-*_])([ ]{,2}\k){2,}[ \t]*+$ - ) - comment: | - We could also use an empty end match and set - applyEndPatternLast, but then we must be sure that the begin - pattern will only match stuff matched by the sub-patterns. - push: - - meta_scope: meta.block-level.markdown - - match: |- - (?x)^ - (?! [ ]{,3}> - | ([ ]{4}|\t) - | [#]{1,6}\s*+ - | [ ]{,3}(?[-*_])([ ]{,2}\k){2,}[ \t]*+$ - ) - pop: true - - include: block_quote - - include: block_raw - - include: heading - - include: separator - - match: '^[ ]{0,3}([*+-])(?=\s)' - captures: - 1: punctuation.definition.list_item.markdown - push: - - meta_scope: markup.list.unnumbered.markdown - - match: ^(?=\S) - captures: - 1: punctuation.definition.list_item.markdown - pop: true - - include: fenced-code-blocks - - include: block_quote - - include: list-paragraph - - match: '^[ ]{0,3}([0-9]+\.)(?=\s)' - captures: - 1: punctuation.definition.list_item.markdown - push: - - meta_scope: markup.list.numbered.markdown - - match: ^(?=\S) - captures: - 1: punctuation.definition.list_item.markdown - pop: true - - include: fenced-code-blocks - - include: block_quote - - include: list-paragraph - - include: fenced-code-blocks - - match: ' - - name - WordHighlight - scope - wordhighlight - settings - - foreground - #dedede - background - #FF420077 - - - - name - BracketHighlighter - scope - brackethighlighter.default - settings - - foreground - #dedede - background - #FF420077 - - - - - name - GitGutter deleted - scope - markup.deleted.git_gutter - settings - - foreground - #F92672 - - - - name - GitGutter inserted - scope - markup.inserted.git_gutter - settings - - foreground - #A6E22E - - - - name - GitGutter changed - scope - markup.changed.git_gutter - settings - - foreground - #967EFB - - - - name - GitGutter ignored - scope - markup.ignored.git_gutter - settings - - foreground - #565656 - - - - name - GitGutter untracked - scope - markup.untracked.git_gutter - settings - - foreground - #565656 - - - - uuid - BF4E1964-0DB9-4E88-8142-E8F52D7EDEEC - - diff --git a/MarkdownEditor-Dark.tmTheme b/MarkdownEditor-Dark.tmTheme deleted file mode 100644 index 87e6931a..00000000 --- a/MarkdownEditor-Dark.tmTheme +++ /dev/null @@ -1,904 +0,0 @@ - - - - - name - MarkdownEditing - settings - - - settings - - background - #131313 - caret - #00bbff - foreground - #aaaaaa - invisibles - #1f1f1f - lineHighlight - #191919 - selection - #3d1700 - selectionBorder - #553420 - inactiveSelection - #4a2c1a - findHighlight - #00186d - findHighlightForeground - #ffffff - shadow - #7f7f7f - shadowWidth - 6 - - - - name - Comments - scope - comment, comment punctuation - settings - - fontStyle - - foreground - #525252 - - - - name - Comments: Preprocessor - scope - comment.block.preprocessor - settings - - fontStyle - - foreground - #525252 - - - - name - Invalid - Deprecated - scope - invalid.deprecated - settings - - background - #103030 - fontStyle - italic underline - - - - name - Invalid - Illegal - scope - invalid.illegal - settings - - fontStyle - - foreground - #060d31 - - - - name - Operators - scope - keyword.operator - settings - - fontStyle - - foreground - #9d9036 - - - - name - Keywords - scope - keyword, storage - settings - - fontStyle - - foreground - #9e79d0 - - - - name - Types - scope - storage.type, support.type - settings - - fontStyle - - foreground - #98ff46 - - - - name - Functions - scope - entity.name.function, support.function, entity - settings - - fontStyle - - foreground - #9e79d0 - - - - name - Classes - scope - entity.name.type, entity.other.inherited-class, support.class - settings - - fontStyle - - foreground - #c5e28d - - - - name - Exceptions - scope - entity.name.exception - settings - - foreground - #06cdcd - - - - name - Sections - scope - entity.name.section,entity.name.section.markdown - settings - - fontStyle - bold - foreground - #cccccc - - - - name - Numbers - scope - constant.numeric, constant - settings - - background - #0c0d00 - fontStyle - - foreground - #89ac3e - - - - name - Punctuation - scope - punctuation - settings - - fontStyle - - foreground - #ffffff - - - - name - Strings - scope - constant.character, string - settings - - background - #0416521A - fontStyle - - foreground - #4398f0 - - - - name - Strings: Punctuation - scope - string punctuation - settings - - fontStyle - - foreground - #1965b3 - - - - name - Strings: Escape Sequences - scope - constant.character.escape - settings - - background - #041652CC - fontStyle - bold - - - - name - Strings: Symbols - scope - constant.other.symbol - settings - - background - #17002a - fontStyle - bold - - - - name - Embedded Source - scope - string source, text source - settings - - foreground - #bcbcbc - - - - - name - HTML: Doctype Declaration - scope - meta.tag.sgml.doctype - settings - - fontStyle - - foreground - #808080 - - - - name - HTML: Tags - scope - - , text.html.markdown meta.disable-markdown entity.name.tag, - , text.html.markdown meta.disable-markdown meta.tag, - , text.html.markdown meta.disable-markdown meta.tag punctuation.definition.tag, - , text.html.markdown meta.disable-markdown meta.tag string.quoted meta.string-contents, - , text.html.markdown meta.disable-markdown meta.tag string.quoted punctuation.definition.string, - , text.html.markdown meta.disable-markdown meta.tag entity.other.attribute-name, - , text.html.markdown meta.paragraph.markdown entity.name.tag, - , text.html.markdown meta.paragraph.markdown meta.tag, - , text.html.markdown meta.paragraph.markdown meta.tag punctuation.definition.tag, - , text.html.markdown meta.paragraph.markdown meta.tag string.quoted meta.string-contents, - , text.html.markdown meta.paragraph.markdown meta.tag string.quoted punctuation.definition.string, - , text.html.markdown meta.paragraph.markdown meta.tag entity.other.attribute-name, - , text.html.markdown markup.list entity.name.tag, - , text.html.markdown markup.list meta.tag, - , text.html.markdown markup.list meta.tag punctuation.definition.tag, - , text.html.markdown markup.list meta.tag string.quoted meta.string-contents, - , text.html.markdown markup.list meta.tag string.quoted punctuation.definition.string, - , text.html.markdown markup.list meta.tag entity.other.attribute-name, - - settings - - foreground - #555555 - background - #131313 - - - - name - HTML: Embedded - scope - source.smarty.embedded.html - settings - - foreground - #888888 - - - - name - HTML: Attribute Punctuation - scope - meta.tag string punctuation,punctuation.definition.entity.html - settings - - foreground - #6e5330 - - - - name - HTML: Tag Punctuation - scope - punctuation.definition.tag - settings - - foreground - #6e5330 - - - - name - HTML: Entities - scope - constant.character.entity - settings - - foreground - #926730 - - - - name - HTML: Attribute Names - scope - entity.other.attribute-name, text.html.markdown meta.disable-markdown meta.tag.block.any.html string.quoted.double.html, text.html.markdown meta.disable-markdown meta.tag.block.any.html string.quoted.double.html punctuation.definition - settings - - fontStyle - - foreground - #666666 - - - - name - HTML: Attribute Values - scope - meta.tag string.quoted, meta.tag string.quoted constant.character.entity - settings - - foreground - #926730 - - - - - name - Markup: Emphasis - scope - markup.italic, markup.italic.markdown - settings - - fontStyle - italic - foreground - #888888 - background - #171717 - - - - name - Markdown: Link - scope - string.other.link.title.markdown,string.other.link.description.markdown - settings - - foreground - #cccccc - background - #22222200 - - - - name - Markdown: Punctuation - scope - punctuation.definition.metadata.markdown,punctuation.definition.string.begin.markdown, punctuation.definition.string.end.markdown, punctuation.definition.constant.markdown, punctuation.separator.key-value.markdown, punctuation.definition.constant.begin.markdown, punctuation.definition.constant.end.markdown,punctuation.definition.bold.markdown, punctuation.definition.italic.markdown, punctuation.definition.strikethrough.markdown, punctuation.definition.heading.markdown - settings - - foreground - #555555 - background - #11111100 - - - - - name - Markdown: Lists - scope - - , markup.list.unnumbered.markdown, - , markup.list.unnumbered.markdown meta.paragraph.list.markdown, - , markup.list.numbered.markdown, - , markup.list.numbered.markdown meta.paragraph.list.markdown, - - settings - - foreground - #999999 - background - #11111100 - - - - name - Markdown: Lists - scope - - , markup.list.unnumbered.markdown punctuation.definition.list_item.markdown, - , markup.list.numbered.markdown punctuation.definition.list_item.markdown, - - settings - - foreground - #ffffff - - - - name - Markup: Output - scope - markup.output, markup.raw - settings - - foreground - #808080 - - - - name - Markup: Prompt - scope - markup.prompt - settings - - foreground - #aaaaaa - - - - name - Markup: Heading - scope - markup.heading - settings - - fontStyle - bold - - - - name - Markup: StrongEmphasis - scope - markup.bold_italic, markup.bold_italic.markdown - settings - - fontStyle - bold italic - foreground - #aaaaaa - - - - name - Markup: Strong - scope - markup.bold, markup.bold.markdown - settings - - fontStyle - bold - foreground - #aaaaaa - - - - name - Markup: Strikethrough - scope - - , markup.strikethrough, - , markup.strikethrough.markdown, - , markup.strikethrough constant.other.reference.link.markdown, - , markup.strikethrough entity.name.tag, - , markup.strikethrough markup.bold, - , markup.strikethrough markup.bold.markdown, - , markup.strikethrough markup.italic, - , markup.strikethrough markup.italic.markdown, - , markup.strikethrough markup.raw.inline.markdown, - , markup.strikethrough markup.underline.link.image.markdown, - , markup.strikethrough markup.underline.link.markdown, - , markup.strikethrough meta.link.inet.markdown markup.underline.link.markdown, - , markup.strikethrough meta.link.email.lt-gt.markdown markup.underline.link.markdown, - , markup.strikethrough punctuation.definition.bold.markdown, - , markup.strikethrough punctuation.definition.italic.markdown, - , markup.strikethrough punctuation.definition.constant.begin.markdown, - , markup.strikethrough punctuation.definition.constant.end.markdown, - , markup.strikethrough punctuation.definition.constant.markdown, - , markup.strikethrough punctuation.definition.metadata.markdown, - , markup.strikethrough punctuation.definition.raw.markdown, - , markup.strikethrough punctuation.definition.strikethrough.markdown, - , markup.strikethrough punctuation.definition.string.begin.markdown, - , markup.strikethrough punctuation.definition.string.end.markdown, - , markup.strikethrough punctuation.definition.tag.begin.html, - , markup.strikethrough punctuation.definition.tag.end.html, - , markup.strikethrough string.other.link.description.markdown, - , markup.strikethrough string.other.link.description.title.markdown, - , markup.strikethrough string.other.link.title.markdown, - - settings - - foreground - #313131 - background - #131313 - - - - name - Markup: Strikethrough (Keyboard Shortcut) - scope - - , markup.strikethrough markup.kbd.content, - , markup.strikethrough markup.kbd.content.markdown, - - settings - - foreground - #484848 - background - #222222 - - - - name - Markup: Keyboard Shortcut - scope - markup.kbd.content.markdown - settings - - background - #2C2C2C - foreground - #ECECEC - - - - name - Markup: Traceback - scope - markup.traceback - settings - - foreground - #06cdcd - - - - name - Markup: Underline - scope - markup.underline,markup.underline.link.markdown,constant.other.reference.link.markdown,meta.image.reference.markdown,meta.image.inline.markdown - settings - - background - #171717 - foreground - #555555 - - - - name - Markup: Plain Link - scope - - , meta.link.inet.markdown markup.underline.link.markdown, - , meta.link.email.lt-gt.markdown markup.underline.link.markdown, - - settings - - foreground - #bbbb77 - - - - - name - Extra: Diff Range - scope - meta.diff.range, meta.diff.index, meta.separator - settings - - background - #150d0a - fontStyle - - foreground - #bcbcbc - - - - name - Extra: Diff From - scope - meta.diff.header.from-file - settings - - background - #002222 - foreground - #bcbcbc - - - - name - Extra: Diff To - scope - meta.diff.header.to-file - settings - - background - #220022 - foreground - #bcbcbc - - - - name - Markdown Meta - scope - meta.header.multimarkdown,keyword.other.multimarkdown,string.unquoted.multimarkdown,punctuation.separator.key-value.multimarkdown - settings - - background - #222222 - foreground - #444444 - - - - name - Markdown separator - scope - meta.separator.markdown - settings - - background - #44444422 - foreground - #555555 - - - - name - Blockquote - scope - markup.quote.markdown - settings - - foreground - #666666 - - - - name - Blockquote (Tags) - scope - - , text.html.markdown markup.quote.markdown entity.name.tag, - , text.html.markdown markup.quote.markdown meta.tag, - , text.html.markdown markup.quote.markdown meta.tag punctuation.definition.tag, - , text.html.markdown markup.quote.markdown meta.tag string.quoted meta.string-contents, - , text.html.markdown markup.quote.markdown meta.tag string.quoted punctuation.definition.string, - , text.html.markdown markup.quote.markdown meta.tag entity.other.attribute-name, - - settings - - foreground - #313131 - background - #131313 - - - - name - Blockquote (Keyboard Shortcut) - scope - text.html.markdown markup.quote.markdown markup.kbd.content.markdown - settings - - background - #1a1a1a - foreground - #8e8e8e - - - - name - Blockquote (Bold) - scope - - , text.html.markdown markup.quote.markdown markup.bold, - , text.html.markdown markup.quote.markdown markup.bold.markdown, - - settings - - foreground - #666666 - - - - name - Blockquote punctuation - scope - punctuation.definition.blockquote.markdown - settings - - background - #3E3E3E - foreground - #3E3E3E - - - - name - Block code - scope - markup.raw.block.markdown - settings - - background - #212121 - foreground - #aaaaaa - - - - name - Inline code - scope - markup.raw.inline.markdown - settings - - background - #212121 - - - - name - Block Cursor - scope - block_cursor - settings - - foreground - #dedede - background - #FF420077 - - - - name - Brackets - scope - entity.name.class - settings - - background - #2A090088 - - - - - - name - WordHighlight - scope - wordhighlight - settings - - foreground - #dedede - background - #FF420077 - - - - name - BracketHighlighter - scope - brackethighlighter.default - settings - - foreground - #dedede - background - #FF420077 - - - - - name - GitGutter deleted - scope - markup.deleted.git_gutter - settings - - foreground - #F92672 - - - - name - GitGutter inserted - scope - markup.inserted.git_gutter - settings - - foreground - #A6E22E - - - - name - GitGutter changed - scope - markup.changed.git_gutter - settings - - foreground - #967EFB - - - - name - GitGutter ignored - scope - markup.ignored.git_gutter - settings - - foreground - #565656 - - - - name - GitGutter untracked - scope - markup.untracked.git_gutter - settings - - foreground - #565656 - - - - uuid - BF4E1964-0DB9-4E88-8142-E8F52D7EDEEC - - diff --git a/MarkdownEditor-Focus.tmTheme b/MarkdownEditor-Focus.tmTheme deleted file mode 100644 index 29cf23b3..00000000 --- a/MarkdownEditor-Focus.tmTheme +++ /dev/null @@ -1,882 +0,0 @@ - - - - - name - MarkdownEditing - settings - - - settings - - background - #cccccc - caret - #00bdff - foreground - #666666 - invisibles - #E0E0E0 - lineHighlight - #f3f3f3 - selection - #C2E8FF - selectionBorder - #AACBDF - inactiveSelection - #B5D3E5 - findHighlight - #FFE792 - findHighlightForeground - #000000 - - - - name - Comments - scope - comment, comment punctuation - settings - - fontStyle - - foreground - #ADADAD - - - - name - Comments: Preprocessor - scope - comment.block.preprocessor - settings - - fontStyle - - foreground - #ADADAD - - - - name - Comments: Documentation - scope - comment.documentation, comment.block.documentation - settings - - background - #FFFDF7 - fontStyle - - foreground - #BC670F - - - - name - Invalid - Deprecated - scope - invalid.deprecated - settings - - background - #EFCFCF - fontStyle - italic underline - - - - name - Invalid - Illegal - scope - invalid.illegal - settings - - fontStyle - - foreground - #F9F2CE - - - - name - Operators - scope - keyword.operator - settings - - fontStyle - - foreground - #626FC9 - - - - name - Keywords - scope - keyword, storage - settings - - fontStyle - - foreground - #61862F - - - - name - Types - scope - storage.type, support.type - settings - - fontStyle - - foreground - #6700B9 - - - - name - Language Constants - scope - constant.language, support.constant, variable.language - settings - - background - #E8E8E8 - fontStyle - - foreground - #7653C1 - - - - name - Variables - scope - variable, support.variable - settings - - fontStyle - - foreground - #4C8FC7 - - - - name - Variables: Punctuation - scope - variable punctuation - settings - - fontStyle - - foreground - #4C8FC7 - - - - name - Functions - scope - entity.name.function, support.function, entity - settings - - fontStyle - - foreground - #61862F - - - - name - Classes - scope - entity.name.type, entity.other.inherited-class, support.class - settings - - fontStyle - - foreground - #3A1D72 - - - - name - Exceptions - scope - entity.name.exception - settings - - foreground - #F93232 - - - - name - Sections - scope - entity.name.section,entity.name.section.markdown - settings - - fontStyle - bold - foreground - #666666 - - - - name - Numbers - scope - constant.numeric, constant - settings - - background - #F3F2FF - fontStyle - - foreground - #7653C1 - - - - name - Punctuation - scope - punctuation - settings - - fontStyle - - foreground - #000000 - - - - name - Strings - scope - constant.character, string - settings - - background - #FBE9AD1A - fontStyle - - foreground - #BC670F - - - - name - Strings: Punctuation - scope - string punctuation - settings - - fontStyle - - foreground - #E69A4C - - - - name - Strings: Escape Sequences - scope - constant.character.escape - settings - - background - #FBE9ADCC - fontStyle - bold - - - - name - Strings: Regular Expressions - scope - string.regexp - settings - - fontStyle - - foreground - #699D36 - - - - name - Strings: Symbols - scope - constant.other.symbol - settings - - background - #E8FFD5 - fontStyle - bold - - - - name - Embedded Source - scope - string source, text source - settings - - fontStyle - - foreground - #434343 - - - - name - ----------------------------------- - settings - - fontStyle - - - - - name - HTML: Doctype Declaration - scope - meta.tag.sgml.doctype - settings - - fontStyle - - foreground - #7F7F7F - - - - name - HTML: Tags - scope - text.html.markdown entity.name.tag,text.html.markdown punctuation.definition.tag.html - settings - - background - #DDDDDD00 - fontStyle - - foreground - #AAAAAA - - - - name - HTML: Tags - scope - meta.disable-markdown - settings - - background - #DDDDDD00 - fontStyle - - foreground - #999999 - - - - name - HTML: Attribute Punctuation - scope - meta.tag string punctuation - settings - - fontStyle - - foreground - #5FAFEF - - - - name - HTML: Tag Punctuation - scope - punctuation.definition.tag - settings - - fontStyle - - foreground - #4F9FCF - - - - name - HTML: Entities - scope - constant.character.entity - settings - - fontStyle - - foreground - #000000 - - - - name - HTML: Attribute Names - scope - entity.other.attribute-name - settings - - fontStyle - - foreground - #4F9FCF - - - - name - HTML: Attribute Values - scope - meta.tag string.quoted, meta.tag string.quoted constant.character.entity - settings - - background - #FFFFFF - fontStyle - - foreground - #D44950 - - - - name - ----------------------------------- - settings - - fontStyle - - - - - name - CSS: Selectors - scope - meta.selector, meta.selector entity, meta.selector entity punctuation, entity.name.tag.css - settings - - fontStyle - - foreground - #3A77BF - - - - name - CSS: Property Names - scope - meta.property-name, support.type.property-name - settings - - foreground - #D4430D - - - - name - CSS: Property Values - scope - meta.property-value constant.numeric, meta.property-value constant, meta.property-value keyword - settings - - background - #FFFFFF - fontStyle - - foreground - #43A202 - - - - name - ----------------------------------- - settings - - - - name - Markup: Changed - scope - markup.changed - settings - - background - #FFFFDD - fontStyle - - foreground - #000000 - - - - name - Markup: Deletion - scope - markup.deleted - settings - - background - #FFDDDD - foreground - #000000 - - - - name - Markup: Emphasis - scope - markup.italic, markup.italic.markdown - settings - - fontStyle - italic - foreground - #777777 - - - - name - Markdown: Link - scope - string.other.link.title.markdown,string.other.link.description.markdown - settings - - foreground - #333333 - background - #DDDDDD00 - - - - name - Markdown: Punctuation - scope - punctuation.definition.metadata.markdown,punctuation.definition.string.begin.markdown, punctuation.definition.string.end.markdown, punctuation.definition.constant.markdown, punctuation.separator.key-value.markdown, punctuation.definition.constant.begin.markdown, punctuation.definition.constant.end.markdown,punctuation.definition.bold.markdown, punctuation.definition.italic.markdown, punctuation.definition.heading.markdown - settings - - foreground - #AAAAAA - - - - name - Markdown: Punctuation - scope - markup.list.unnumbered.markdown meta.paragraph.list.markdown, markup.list.unnumbered.markdown punctuation.definition.list_item.markdown, markup.list.numbered.markdown, markup.list.numbered.markdown meta.paragraph.list.markdown, markup.list.numbered.markdown punctuation.definition.list_item.markdown - settings - - foreground - #666666 - - - - name - Markdown: Paragraph - scope - meta.paragraph.markdown - settings - - foreground - #666666aa - - - - name - Markup: Error - scope - markup.error - settings - - background - #F93232 - fontStyle - - foreground - #F9F2CE - - - - name - Markup: Insertion - scope - markup.inserted - settings - - background - #DDFFDD - fontStyle - - foreground - #000000 - - - - name - Markup: Output - scope - markup.output, markup.raw - settings - - foreground - #7F7F7F - - - - name - Markup: Prompt - scope - markup.prompt - settings - - foreground - #555555 - - - - name - Markup: Heading - scope - markup.heading - settings - - fontStyle - bold - - - - name - Markup: Heading - scope - markup.heading.markdown - settings - - fontStyle - bold - foreground - #777777 - - - - name - Markup: StrongEmphasis - scope - markup.bold_italic, markup.bold_italic.markdown - settings - - fontStyle - bold italic - foreground - #777777 - - - - name - Markup: Strong - scope - markup.bold, markup.bold.markdown - settings - - fontStyle - bold - foreground - #777777 - - - - name - Markup: Traceback - scope - markup.traceback - settings - - foreground - #F93232 - - - - name - Markup: Underline - scope - markup.underline,markup.underline.link.markdown,constant.other.reference.link.markdown,meta.image.reference.markdown,meta.image.inline.markdown - settings - - background - #E8E8E8 - foreground - #AAAAAA - - - - name - ----------------------------------- - settings - - - - name - Extra: Diff Range - scope - meta.diff.range, meta.diff.index, meta.separator - settings - - background - #EAF2F5 - fontStyle - - foreground - #434343 - - - - name - Extra: Diff From - scope - meta.diff.header.from-file - settings - - background - #FFDDDD - foreground - #434343 - - - - name - Extra: Diff To - scope - meta.diff.header.to-file - settings - - background - #DDFFDD - foreground - #434343 - - - - name - Markdown Meta - scope - meta.header.multimarkdown,keyword.other.multimarkdown,string.unquoted.multimarkdown,punctuation.separator.key-value.multimarkdown - settings - - background - #DDDDDD - foreground - #BBBBBB - - - - name - Markdown separator - scope - meta.separator.markdown - settings - - background - #BBBBBB - foreground - #AAAAAA - - - - name - Block Cursor - scope - block_cursor - settings - - foreground - #212121 - background - #00bdff77 - - - - name - Brackets - scope - entity.name.class - settings - - background - #d5f6ff88 - - - - - name - GitGutter deleted - scope - markup.deleted.git_gutter - settings - - foreground - #F92672 - - - - name - GitGutter inserted - scope - markup.inserted.git_gutter - settings - - foreground - #A6E22E - - - - name - GitGutter changed - scope - markup.changed.git_gutter - settings - - foreground - #967EFB - - - - name - GitGutter ignored - scope - markup.ignored.git_gutter - settings - - foreground - #565656 - - - - name - GitGutter untracked - scope - markup.untracked.git_gutter - settings - - foreground - #565656 - - - - uuid - BF4E1964-0DB9-4E88-8142-E8F52D7EDEEC - - diff --git a/MarkdownEditor-Yellow.tmTheme b/MarkdownEditor-Yellow.tmTheme deleted file mode 100644 index 428e5ae0..00000000 --- a/MarkdownEditor-Yellow.tmTheme +++ /dev/null @@ -1,904 +0,0 @@ - - - - - name - MarkdownEditing - settings - - - settings - - background - #efe9b7 - caret - #28bbc6 - foreground - #705442 - invisibles - #e5ddae - lineHighlight - #eae3b2 - selection - #cce5c6 - selectionBorder - #b7c8ad - inactiveSelection - #c1d0b2 - findHighlight - #ffe471 - findHighlightForeground - #280000 - shadow - #947e63 - shadowWidth - 6 - - - - name - Comments - scope - comment, comment punctuation - settings - - fontStyle - - foreground - #baab86 - - - - name - Comments: Preprocessor - scope - comment.block.preprocessor - settings - - fontStyle - - foreground - #baab86 - - - - name - Invalid - Deprecated - scope - invalid.deprecated - settings - - background - #f2cca1 - fontStyle - italic underline - - - - name - Invalid - Illegal - scope - invalid.illegal - settings - - fontStyle - - foreground - #faefa0 - - - - name - Operators - scope - keyword.operator - settings - - fontStyle - - foreground - #7b6e9c - - - - name - Keywords - scope - keyword, storage - settings - - fontStyle - - foreground - #7a8424 - - - - name - Types - scope - storage.type, support.type - settings - - fontStyle - - foreground - #7f008f - - - - name - Functions - scope - entity.name.function, support.function, entity - settings - - fontStyle - - foreground - #7a8424 - - - - name - Classes - scope - entity.name.type, entity.other.inherited-class, support.class - settings - - fontStyle - - foreground - #591d58 - - - - name - Exceptions - scope - entity.name.exception - settings - - foreground - #fa3127 - - - - name - Sections - scope - entity.name.section,entity.name.section.markdown - settings - - fontStyle - bold - foreground - #533228 - - - - name - Numbers - scope - constant.numeric, constant - settings - - background - #f5efc6 - fontStyle - - foreground - #8c5296 - - - - name - Punctuation - scope - punctuation - settings - - fontStyle - - foreground - #280000 - - - - name - Strings - scope - constant.character, string - settings - - background - #fce6861A - fontStyle - - foreground - #c7660c - - - - name - Strings: Punctuation - scope - string punctuation - settings - - fontStyle - - foreground - #ea983b - - - - name - Strings: Escape Sequences - scope - constant.character.escape - settings - - background - #fce686CC - fontStyle - bold - - - - name - Strings: Symbols - scope - constant.other.symbol - settings - - background - #ecfca5 - fontStyle - bold - - - - name - Embedded Source - scope - string source, text source - settings - - foreground - #614234 - - - - - name - HTML: Doctype Declaration - scope - meta.tag.sgml.doctype - settings - - fontStyle - - foreground - #937d62 - - - - name - HTML: Tags - scope - - , text.html.markdown meta.disable-markdown entity.name.tag, - , text.html.markdown meta.disable-markdown meta.tag, - , text.html.markdown meta.disable-markdown meta.tag punctuation.definition.tag, - , text.html.markdown meta.disable-markdown meta.tag string.quoted meta.string-contents, - , text.html.markdown meta.disable-markdown meta.tag string.quoted punctuation.definition.string, - , text.html.markdown meta.disable-markdown meta.tag entity.other.attribute-name, - , text.html.markdown meta.paragraph.markdown entity.name.tag, - , text.html.markdown meta.paragraph.markdown meta.tag, - , text.html.markdown meta.paragraph.markdown meta.tag punctuation.definition.tag, - , text.html.markdown meta.paragraph.markdown meta.tag string.quoted meta.string-contents, - , text.html.markdown meta.paragraph.markdown meta.tag string.quoted punctuation.definition.string, - , text.html.markdown meta.paragraph.markdown meta.tag entity.other.attribute-name, - , text.html.markdown markup.list entity.name.tag, - , text.html.markdown markup.list meta.tag, - , text.html.markdown markup.list meta.tag punctuation.definition.tag, - , text.html.markdown markup.list meta.tag string.quoted meta.string-contents, - , text.html.markdown markup.list meta.tag string.quoted punctuation.definition.string, - , text.html.markdown markup.list meta.tag entity.other.attribute-name, - - settings - - foreground - #b7a884 - background - #efe9b7 - - - - name - HTML: Embedded - scope - source.smarty.embedded.html - settings - - foreground - #8c755c - - - - name - HTML: Attribute Punctuation - scope - meta.tag string punctuation,punctuation.definition.entity.html - settings - - foreground - #a2aaa1 - - - - name - HTML: Tag Punctuation - scope - punctuation.definition.tag - settings - - foreground - #a2aaa1 - - - - name - HTML: Entities - scope - constant.character.entity - settings - - foreground - #8496a1 - - - - name - HTML: Attribute Names - scope - entity.other.attribute-name, text.html.markdown meta.disable-markdown meta.tag.block.any.html string.quoted.double.html, text.html.markdown meta.disable-markdown meta.tag.block.any.html string.quoted.double.html punctuation.definition - settings - - fontStyle - - foreground - #a99777 - - - - name - HTML: Attribute Values - scope - meta.tag string.quoted, meta.tag string.quoted constant.character.entity - settings - - foreground - #8496a1 - - - - - name - Markup: Emphasis - scope - markup.italic, markup.italic.markdown - settings - - fontStyle - italic - foreground - #8c755c - background - #ece5b4 - - - - name - Markdown: Link - scope - string.other.link.title.markdown,string.other.link.description.markdown - settings - - foreground - #533228 - background - #e2daab00 - - - - name - Markdown: Punctuation - scope - punctuation.definition.metadata.markdown,punctuation.definition.string.begin.markdown, punctuation.definition.string.end.markdown, punctuation.definition.constant.markdown, punctuation.separator.key-value.markdown, punctuation.definition.constant.begin.markdown, punctuation.definition.constant.end.markdown,punctuation.definition.bold.markdown, punctuation.definition.italic.markdown, punctuation.definition.strikethrough.markdown, punctuation.definition.heading.markdown - settings - - foreground - #b7a884 - background - #f1ebb900 - - - - - name - Markdown: Lists - scope - - , markup.list.unnumbered.markdown, - , markup.list.unnumbered.markdown meta.paragraph.list.markdown, - , markup.list.numbered.markdown, - , markup.list.numbered.markdown meta.paragraph.list.markdown, - - settings - - foreground - #7e654f - background - #f1ebb900 - - - - name - Markdown: Lists - scope - - , markup.list.unnumbered.markdown punctuation.definition.list_item.markdown, - , markup.list.numbered.markdown punctuation.definition.list_item.markdown, - - settings - - foreground - #280000 - - - - name - Markup: Output - scope - markup.output, markup.raw - settings - - foreground - #937d62 - - - - name - Markup: Prompt - scope - markup.prompt - settings - - foreground - #705442 - - - - name - Markup: Heading - scope - markup.heading - settings - - fontStyle - bold - - - - name - Markup: StrongEmphasis - scope - markup.bold_italic, markup.bold_italic.markdown - settings - - fontStyle - bold italic - foreground - #705442 - - - - name - Markup: Strong - scope - markup.bold, markup.bold.markdown - settings - - fontStyle - bold - foreground - #705442 - - - - name - Markup: Strikethrough - scope - - , markup.strikethrough, - , markup.strikethrough.markdown, - , markup.strikethrough constant.other.reference.link.markdown, - , markup.strikethrough entity.name.tag, - , markup.strikethrough markup.bold, - , markup.strikethrough markup.bold.markdown, - , markup.strikethrough markup.italic, - , markup.strikethrough markup.italic.markdown, - , markup.strikethrough markup.raw.inline.markdown, - , markup.strikethrough markup.underline.link.image.markdown, - , markup.strikethrough markup.underline.link.markdown, - , markup.strikethrough meta.link.inet.markdown markup.underline.link.markdown, - , markup.strikethrough meta.link.email.lt-gt.markdown markup.underline.link.markdown, - , markup.strikethrough punctuation.definition.bold.markdown, - , markup.strikethrough punctuation.definition.italic.markdown, - , markup.strikethrough punctuation.definition.constant.begin.markdown, - , markup.strikethrough punctuation.definition.constant.end.markdown, - , markup.strikethrough punctuation.definition.constant.markdown, - , markup.strikethrough punctuation.definition.metadata.markdown, - , markup.strikethrough punctuation.definition.raw.markdown, - , markup.strikethrough punctuation.definition.strikethrough.markdown, - , markup.strikethrough punctuation.definition.string.begin.markdown, - , markup.strikethrough punctuation.definition.string.end.markdown, - , markup.strikethrough punctuation.definition.tag.begin.html, - , markup.strikethrough punctuation.definition.tag.end.html, - , markup.strikethrough string.other.link.description.markdown, - , markup.strikethrough string.other.link.description.title.markdown, - , markup.strikethrough string.other.link.title.markdown, - - settings - - foreground - #d6cba0 - background - #efe9b7 - - - - name - Markup: Strikethrough (Keyboard Shortcut) - scope - - , markup.strikethrough markup.kbd.content, - , markup.strikethrough markup.kbd.content.markdown, - - settings - - foreground - #c2b58e - background - #e2daab - - - - name - Markup: Keyboard Shortcut - scope - markup.kbd.content.markdown - settings - - background - #dad0a4 - foreground - #38130f - - - - name - Markup: Traceback - scope - markup.traceback - settings - - foreground - #fa3127 - - - - name - Markup: Underline - scope - markup.underline,markup.underline.link.markdown,constant.other.reference.link.markdown,meta.image.reference.markdown,meta.image.inline.markdown - settings - - background - #ece5b4 - foreground - #b7a884 - - - - name - Markup: Plain Link - scope - - , meta.link.inet.markdown markup.underline.link.markdown, - , meta.link.email.lt-gt.markdown markup.underline.link.markdown, - - settings - - foreground - #624369 - - - - - name - Extra: Diff Range - scope - meta.diff.range, meta.diff.index, meta.separator - settings - - background - #edefbe - fontStyle - - foreground - #614234 - - - - name - Extra: Diff From - scope - meta.diff.header.from-file - settings - - background - #ffdaab - foreground - #614234 - - - - name - Extra: Diff To - scope - meta.diff.header.to-file - settings - - background - #e2fcab - foreground - #614234 - - - - name - Markdown Meta - scope - meta.header.multimarkdown,keyword.other.multimarkdown,string.unquoted.multimarkdown,punctuation.separator.key-value.multimarkdown - settings - - background - #e2daab - foreground - #c6b991 - - - - name - Markdown separator - scope - meta.separator.markdown - settings - - background - #c6b99122 - foreground - #b7a884 - - - - name - Blockquote - scope - markup.quote.markdown - settings - - foreground - #a99777 - - - - name - Blockquote (Tags) - scope - - , text.html.markdown markup.quote.markdown entity.name.tag, - , text.html.markdown markup.quote.markdown meta.tag, - , text.html.markdown markup.quote.markdown meta.tag punctuation.definition.tag, - , text.html.markdown markup.quote.markdown meta.tag string.quoted meta.string-contents, - , text.html.markdown markup.quote.markdown meta.tag string.quoted punctuation.definition.string, - , text.html.markdown markup.quote.markdown meta.tag entity.other.attribute-name, - - settings - - foreground - #d6cba0 - background - #efe9b7 - - - - name - Blockquote (Keyboard Shortcut) - scope - text.html.markdown markup.quote.markdown markup.kbd.content.markdown - settings - - background - #e9e2b2 - foreground - #877058 - - - - name - Blockquote (Bold) - scope - - , text.html.markdown markup.quote.markdown markup.bold, - , text.html.markdown markup.quote.markdown markup.bold.markdown, - - settings - - foreground - #a99777 - - - - name - Blockquote punctuation - scope - punctuation.definition.blockquote.markdown - settings - - background - #d7cda1 - foreground - #d7cda1 - - - - name - Block code - scope - markup.raw.block.markdown - settings - - background - #e3dbac - foreground - #705442 - - - - name - Inline code - scope - markup.raw.inline.markdown - settings - - background - #e3dbac - - - - name - Block Cursor - scope - block_cursor - settings - - foreground - #44211a - background - #28bbc677 - - - - name - Brackets - scope - entity.name.class - settings - - background - #dcf3c688 - - - - - - name - WordHighlight - scope - wordhighlight - settings - - foreground - #44211a - background - #28bbc677 - - - - name - BracketHighlighter - scope - brackethighlighter.default - settings - - foreground - #44211a - background - #28bbc677 - - - - - name - GitGutter deleted - scope - markup.deleted.git_gutter - settings - - foreground - #F92672 - - - - name - GitGutter inserted - scope - markup.inserted.git_gutter - settings - - foreground - #46A524 - - - - name - GitGutter changed - scope - markup.changed.git_gutter - settings - - foreground - #700DDB - - - - name - GitGutter ignored - scope - markup.ignored.git_gutter - settings - - foreground - #565656 - - - - name - GitGutter untracked - scope - markup.untracked.git_gutter - settings - - foreground - #565656 - - - - uuid - BF4E1964-0DB9-4E88-8142-E8F52D7EDEEC - - diff --git a/MarkdownEditor.tmTheme b/MarkdownEditor.tmTheme deleted file mode 100644 index 2a0d903e..00000000 --- a/MarkdownEditor.tmTheme +++ /dev/null @@ -1,968 +0,0 @@ - - - - - name - MarkdownEditing - settings - - - settings - - background - #ECECEC - caret - #00bbff - foreground - #555555 - invisibles - #E0E0E0 - lineHighlight - #D3D3D3 - selection - #C2E8FF - selectionBorder - #AACBDF - inactiveSelection - #B5D3E5 - findHighlight - #FFE792 - findHighlightForeground - #000000 - shadow - #808080 - shadowWidth - 6 - - - - name - Comments - scope - comment, comment punctuation - settings - - fontStyle - - foreground - #ADADAD - - - - name - Comments: Preprocessor - scope - comment.block.preprocessor - settings - - fontStyle - - foreground - #ADADAD - - - - name - Invalid - Deprecated - scope - invalid.deprecated - settings - - background - #EFCFCF - fontStyle - italic underline - - - - name - Invalid - Illegal - scope - invalid.illegal - settings - - fontStyle - - foreground - #F9F2CE - - - - name - Operators - scope - keyword.operator - settings - - fontStyle - - foreground - #626FC9 - - - - name - Keywords - scope - keyword, storage - settings - - fontStyle - - foreground - #61862F - - - - name - Types - scope - storage.type, support.type - settings - - fontStyle - - foreground - #6700B9 - - - - name - Functions - scope - entity.name.function, support.function, entity - settings - - fontStyle - - foreground - #61862F - - - - name - Classes - scope - entity.name.type, entity.other.inherited-class, support.class - settings - - fontStyle - - foreground - #3A1D72 - - - - name - Exceptions - scope - entity.name.exception - settings - - foreground - #F93232 - - - - name - Sections - scope - entity.name.section,entity.name.section.markdown - settings - - fontStyle - bold - foreground - #333333 - - - - name - Numbers - scope - constant.numeric, constant - settings - - background - #F3F2FF - fontStyle - - foreground - #7653C1 - - - - name - Punctuation - scope - punctuation - settings - - fontStyle - - foreground - #000000 - - - - name - Strings - scope - constant.character, string - settings - - background - #FBE9AD1A - fontStyle - - foreground - #BC670F - - - - name - Strings: Punctuation - scope - string punctuation - settings - - fontStyle - - foreground - #E69A4C - - - - name - Strings: Escape Sequences - scope - constant.character.escape - settings - - background - #FBE9ADCC - fontStyle - bold - - - - name - Strings: Symbols - scope - constant.other.symbol - settings - - background - #E8FFD5 - fontStyle - bold - - - - name - Embedded Source - scope - string source, text source - settings - - foreground - #434343 - - - - - name - HTML: Doctype Declaration - scope - meta.tag.sgml.doctype - settings - - fontStyle - - foreground - #7F7F7F - - - - name - HTML: Tags - scope - - , text.html.markdown meta.disable-markdown entity.name.tag, - , text.html.markdown meta.disable-markdown meta.tag, - , text.html.markdown meta.disable-markdown meta.tag punctuation.definition.tag, - , text.html.markdown meta.disable-markdown meta.tag string.quoted meta.string-contents, - , text.html.markdown meta.disable-markdown meta.tag string.quoted punctuation.definition.string, - , text.html.markdown meta.disable-markdown meta.tag entity.other.attribute-name, - , text.html.markdown meta.paragraph.markdown entity.name.tag, - , text.html.markdown meta.paragraph.markdown meta.tag, - , text.html.markdown meta.paragraph.markdown meta.tag punctuation.definition.tag, - , text.html.markdown meta.paragraph.markdown meta.tag string.quoted meta.string-contents, - , text.html.markdown meta.paragraph.markdown meta.tag string.quoted punctuation.definition.string, - , text.html.markdown meta.paragraph.markdown meta.tag entity.other.attribute-name, - , text.html.markdown markup.list entity.name.tag, - , text.html.markdown markup.list meta.tag, - , text.html.markdown markup.list meta.tag punctuation.definition.tag, - , text.html.markdown markup.list meta.tag string.quoted meta.string-contents, - , text.html.markdown markup.list meta.tag string.quoted punctuation.definition.string, - , text.html.markdown markup.list meta.tag entity.other.attribute-name, - - settings - - foreground - #AAAAAA - background - #ECECEC - - - - name - HTML: Embedded - scope - source.smarty.embedded.html - settings - - foreground - #777777 - - - - name - HTML: Attribute Punctuation - scope - meta.tag string punctuation,punctuation.definition.entity.html - settings - - foreground - #91accf - - - - name - HTML: Tag Punctuation - scope - punctuation.definition.tag - settings - - foreground - #91accf - - - - name - HTML: Entities - scope - constant.character.entity - settings - - foreground - #6d98cf - - - - name - HTML: Attribute Names - scope - entity.other.attribute-name, text.html.markdown meta.disable-markdown meta.tag.block.any.html string.quoted.double.html, text.html.markdown meta.disable-markdown meta.tag.block.any.html string.quoted.double.html punctuation.definition - settings - - fontStyle - - foreground - #999999 - - - - name - HTML: Attribute Values - scope - meta.tag string.quoted, meta.tag string.quoted constant.character.entity - settings - - foreground - #6d98cf - - - - - name - Markup: Emphasis - scope - markup.italic, markup.italic.markdown - settings - - fontStyle - italic - foreground - #777777 - background - #E8E8E8 - - - - name - Markdown: Link - scope - string.other.link.title.markdown,string.other.link.description.markdown - settings - - foreground - #333333 - background - #DDDDDD00 - - - - name - Markdown: Punctuation - scope - punctuation.definition.metadata.markdown,punctuation.definition.string.begin.markdown, punctuation.definition.string.end.markdown, punctuation.definition.constant.markdown, punctuation.separator.key-value.markdown, punctuation.definition.constant.begin.markdown, punctuation.definition.constant.end.markdown,punctuation.definition.bold.markdown, punctuation.definition.italic.markdown, punctuation.definition.strikethrough.markdown, punctuation.definition.heading.markdown - settings - - foreground - #AAAAAA - background - #EEEEEE00 - - - - - name - Markdown: Lists - scope - - , markup.list.unnumbered.markdown, - , markup.list.unnumbered.markdown meta.paragraph.list.markdown, - , markup.list.numbered.markdown, - , markup.list.numbered.markdown meta.paragraph.list.markdown, - - settings - - foreground - #666666 - background - #EEEEEE00 - - - - name - Markdown: Lists - scope - - , markup.list.unnumbered.markdown punctuation.definition.list_item.markdown, - , markup.list.numbered.markdown punctuation.definition.list_item.markdown, - - settings - - foreground - #000000 - - - - name - Markup: Output - scope - markup.output, markup.raw - settings - - foreground - #7F7F7F - - - - name - Markup: Prompt - scope - markup.prompt - settings - - foreground - #555555 - - - - name - Markup: Heading - scope - markup.heading - settings - - fontStyle - bold - - - - name - Markup: StrongEmphasis - scope - markup.bold_italic, markup.bold_italic.markdown - settings - - fontStyle - bold italic - foreground - #555555 - - - - name - Markup: Strong - scope - markup.bold, markup.bold.markdown - settings - - fontStyle - bold - foreground - #555555 - - - - name - Markup: Strikethrough - scope - - , markup.strikethrough, - , markup.strikethrough.markdown, - , markup.strikethrough constant.other.reference.link.markdown, - , markup.strikethrough entity.name.tag, - , markup.strikethrough markup.bold, - , markup.strikethrough markup.bold.markdown, - , markup.strikethrough markup.italic, - , markup.strikethrough markup.italic.markdown, - , markup.strikethrough markup.raw.inline.markdown, - , markup.strikethrough markup.underline.link.image.markdown, - , markup.strikethrough markup.underline.link.markdown, - , markup.strikethrough meta.link.inet.markdown markup.underline.link.markdown, - , markup.strikethrough meta.link.email.lt-gt.markdown markup.underline.link.markdown, - , markup.strikethrough punctuation.definition.bold.markdown, - , markup.strikethrough punctuation.definition.italic.markdown, - , markup.strikethrough punctuation.definition.constant.begin.markdown, - , markup.strikethrough punctuation.definition.constant.end.markdown, - , markup.strikethrough punctuation.definition.constant.markdown, - , markup.strikethrough punctuation.definition.metadata.markdown, - , markup.strikethrough punctuation.definition.raw.markdown, - , markup.strikethrough punctuation.definition.strikethrough.markdown, - , markup.strikethrough punctuation.definition.string.begin.markdown, - , markup.strikethrough punctuation.definition.string.end.markdown, - , markup.strikethrough punctuation.definition.tag.begin.html, - , markup.strikethrough punctuation.definition.tag.end.html, - , markup.strikethrough string.other.link.description.markdown, - , markup.strikethrough string.other.link.description.title.markdown, - , markup.strikethrough string.other.link.title.markdown, - - settings - - foreground - #CECECE - background - #ECECEC - - - - name - Markup: Strikethrough (Keyboard Shortcut) - scope - - , markup.strikethrough markup.kbd.content, - , markup.strikethrough markup.kbd.content.markdown, - - settings - - foreground - #B7B7B7 - background - #DDDDDD - - - - name - Markup: Keyboard Shortcut - scope - markup.kbd.content.markdown - settings - - background - #D3D3D3 - foreground - #131313 - - - - name - Markup: Traceback - scope - markup.traceback - settings - - foreground - #F93232 - - - - name - Markup: Underline - scope - markup.underline,markup.underline.link.markdown,constant.other.reference.link.markdown,meta.image.reference.markdown,meta.image.inline.markdown - settings - - foreground - #AAAAAA - - - - name - Markup: Plain Link - scope - - , meta.link.inet.markdown markup.underline.link.markdown, - , meta.link.email.lt-gt.markdown markup.underline.link.markdown, - - settings - - foreground - #444488 - - - - - name - Extra: Diff Range - scope - meta.diff.range, meta.diff.index, meta.separator - settings - - background - #EAF2F5 - fontStyle - - foreground - #434343 - - - - name - Extra: Diff From - scope - meta.diff.header.from-file - settings - - background - #FFDDDD - foreground - #434343 - - - - name - Extra: Diff To - scope - meta.diff.header.to-file - settings - - background - #DDFFDD - foreground - #434343 - - - - name - Markdown Meta - scope - meta.header.multimarkdown,keyword.other.multimarkdown,string.unquoted.multimarkdown,punctuation.separator.key-value.multimarkdown - settings - - background - #DDDDDD - foreground - #BBBBBB - - - - name - Markdown separator - scope - meta.separator.markdown - settings - - background - #BBBBBB22 - foreground - #AAAAAA - - - - name - Blockquote - scope - markup.quote.markdown - settings - - foreground - #999999 - - - - name - Blockquote (Tags) - scope - - , text.html.markdown markup.quote.markdown entity.name.tag, - , text.html.markdown markup.quote.markdown meta.tag, - , text.html.markdown markup.quote.markdown meta.tag punctuation.definition.tag, - , text.html.markdown markup.quote.markdown meta.tag string.quoted meta.string-contents, - , text.html.markdown markup.quote.markdown meta.tag string.quoted punctuation.definition.string, - , text.html.markdown markup.quote.markdown meta.tag entity.other.attribute-name, - - settings - - foreground - #CECECE - background - #ECECEC - - - - name - Blockquote (Keyboard Shortcut) - scope - text.html.markdown markup.quote.markdown markup.kbd.content.markdown - settings - - background - #e5e5e5 - foreground - #717171 - - - - name - Blockquote (Bold) - scope - - , text.html.markdown markup.quote.markdown markup.bold, - , text.html.markdown markup.quote.markdown markup.bold.markdown, - - settings - - foreground - #999999 - - - - name - Blockquote punctuation - scope - punctuation.definition.blockquote.markdown - settings - - background - #D0D0D0 - foreground - #D0D0D0 - - - - name - Block code - scope - markup.raw.block.markdown - settings - - background - #dedede - foreground - #555555 - - - - name - Inline code - scope - markup.raw.inline.markdown - settings - - background - #dedede - - - - name - Block Cursor - scope - block_cursor - settings - - foreground - #212121 - background - #00bdff77 - - - - name - Brackets - scope - entity.name.class - settings - - background - #d5f6ff88 - - - - - - name - WordHighlight - scope - wordhighlight - settings - - foreground - #212121 - background - #00bdff77 - - - - name - BracketHighlighter - scope - brackethighlighter.default - settings - - foreground - #212121 - background - #00bdff77 - - - - - name - GitGutter deleted - scope - markup.deleted.git_gutter - settings - - foreground - #F92672 - - - - name - GitGutter inserted - scope - markup.inserted.git_gutter - settings - - foreground - #46A524 - - - - name - GitGutter changed - scope - markup.changed.git_gutter - settings - - foreground - #700DDB - - - - name - GitGutter ignored - scope - markup.ignored.git_gutter - settings - - foreground - #565656 - - - - name - GitGutter untracked - scope - markup.untracked.git_gutter - settings - - foreground - #565656 - - - - - - name - Highlight Color Warm Blue - scope - highlight.color.ADD8E6 - settings - - foreground - #ADD8E6 - - - - - name - Highlight Color MistyRose - scope - highlight.color.FFE4E1 - settings - - foreground - #FFE4E1 - - - - - name - Highlight Color Green Tea - scope - highlight.color.D0F0C0 - settings - - foreground - #D0F0C0 - - - - - - name - SublimeLinter: Warning - scope - sublimelinter.mark.warning - settings - - foreground - #DDB700 - - - - - name - SublimeLinter: Error - scope - sublimelinter.mark.error - settings - - foreground - #D02000 - - - - uuid - BF4E1964-0DB9-4E88-8142-E8F52D7EDEEC - - diff --git a/MultiMarkdown.sublime-settings b/MultiMarkdown.sublime-settings deleted file mode 100644 index ca5f232c..00000000 --- a/MultiMarkdown.sublime-settings +++ /dev/null @@ -1,154 +0,0 @@ -{ - "extensions": - [ - "mmd" - ], - - "color_scheme": "Packages/MarkdownEditing/MarkdownEditor.tmTheme", - // "color_scheme": "Packages/MarkdownEditing/MarkdownEditor-Dark.tmTheme", - // "color_scheme": "Packages/MarkdownEditing/MarkdownEditor-Yellow.tmTheme", - - // This is a quick and dirty focus theme. In order to make it work, you've to - // set `"highlight_line": true,` in this settings file. It is likely that there will - // be more mature focus improvements in the future (maybe similar to iA Writer). - // "color_scheme": "Packages/MarkdownEditing/MarkdownEditor-Focus.tmTheme", - - "tab_size": 4, - "translate_tabs_to_spaces": true, - "trim_trailing_white_space_on_save": false, - "auto_match_enabled": true, - - // Layout - "draw_centered": true, - "word_wrap": true, - "wrap_width": 80, - "rulers": [], - - // Line - "line_numbers": false, - "highlight_line": false, - "line_padding_top": 2, - "line_padding_bottom": 2, - - // Caret - "caret_style": "wide", - "caret_extra_top": 3, - "caret_extra_bottom": 3, - - // add trailing #'s to headlines - "mde.match_header_hashes": false, - - // Automatically switches list bullet when indenting blank list item with . - "mde.list_indent_auto_switch_bullet": true, - - // List bullets to be used for automatically switching. In their order. - "mde.list_indent_bullets": ["*", "-", "+"], - - // Auto increments ordered list number. Set to false if you want always "1". - "mde.auto_increment_ordered_list_number": true, - - // Always keep current line vertically centered. - "mde.keep_centered": false, - - // Distraction free mode improvements. In order for these to work, you have to install - // FullScreenStatus plugin: https://github.com/maliayas/SublimeText_FullScreenStatus - "mde.distraction_free_mode": { - "mde.keep_centered": true - }, - - "mde.lint":{ - "mdl": { - // By default it is mdl.bat on windows and mdl otherwise. Leave it blank to use the default value - // If you are using a custom launcher, you may want to change this - "executable": "", - // Extra arguments passed to mdl. For all options, see here: - // https://github.com/markdownlint/markdownlint/blob/master/lib/mdl/cli.rb - // You can also specify a config file with '-c ~/.mdlrc' - "additional_arguments": [] - }, - // disabled rules, e.g. "md001". - "disable": ["md013"], - // Options: - // atx, ## title only - // atx_closed, ## title ## only - // setext, title only - // ===== - // any, consistent within the document - "md003": "any", - // Options: - // asterisk, * only - // plus, + only - // dash, - only - // cyclic, different symbols on different levels - // and same symbol on same level - // single, same symbol on different levels - // any, same symbol on same level - "md004": "cyclic", - // Number of spaces per list indent. Set to 0 to use Sublime tab_size instead - "md007": 0, - // Maximum line length, Set to 0 to use Sublime wrap_width instead - "md013": 0, - // Disallowed trailing punctuation in headers - "md026": ".,;:!", - // Options: - // one, '1.' only - // ordered, ascending number - // any, consistent within one list - "md029": "any", - // (ordered vs unordered, single-line vs multi-line) - "md030": { - "ul_single": 1, - "ol_single": 1, - // optinally, 3 - "ul_multi": 1, - // optionaly, 2 - "ol_multi": 1 - } - }, - - "mde.wikilinks.markdown_extension": ".md", - "mde.wikilinks.homepage": "HomePage", - "mde.wikilinks.templates": { - "default_page": "templates/PageTemplate.md" - }, - - // You can opt out some keybinds by setting the corresponding value from 'false' to 'true' (without single-quotes). - // Super key references to a key next to left Alt key. It usually has a Windows logo or "win" or "Command" on it. - // Jump between link/image/footnote reference and definition - // Default keys: (OSX)super+ctrl+shift+l (Linux/Win)ctrl+alt+g - "mde.keymap_disable.reference_jump": false, - // Add a new link - // Default keys: (OSX)super+alt+r (Linux/Win)ctrl+super+r - "mde.keymap_disable.reference_new_reference": false, - // Add a new inline link - // Default keys: (OSX)super+alt+v (Linux/Win)ctrl+super+v - "mde.keymap_disable.reference_new_inline_link": false, - // Add a new inline image - // Default keys: (OSX/Linux/Win)super+shift+k - "mde.keymap_disable.reference_new_inline_image": false, - // Add a new footnote - // Default keys: (OSX/Linux/Win)alt+shift+6 - "mde.keymap_disable.reference_new_footnote": false, - // Fold current section - // Default keys: (OSX/Linux/Win)shift+tab - "mde.keymap_disable.fold_section": false, - // Open a panel showing all functions related to folding - // Default keys: (OSX/Linux/Win)ctrl+shift+tab - "mde.keymap_disable.show_fold_all_sections": false, - // Jump to the next heading (any level/same or higher level) - // Default keys: (OSX)super+ctrl/shift+pagedown (Linux/Win)ctrl+shift(+alt)+pagedown - "mde.keymap_disable.goto_next_heading": false, - // Jump to the previous heading (any level/same or higher level) - // Default keys: (OSX)super+ctrl/shift+pageup (Linux/Win)ctrl+shift(+alt)+pageup - "mde.keymap_disable.goto_previous_heading": false, - // List pages the link to the current page - "mde.keymap_disable.list_back_links": true, - // Open the home page - "mde.keymap_disable.open_home_page": true, - // Open the journal - "mde.keymap_disable.open_journal": true, - // Open the page referenced - "mde.keymap_disable.open_page": true, - // Make page reference - "mde.keymap_disable.make_page_reference": true -} diff --git a/MultiMarkdown.tmLanguage b/MultiMarkdown.tmLanguage deleted file mode 100644 index acf507ca..00000000 --- a/MultiMarkdown.tmLanguage +++ /dev/null @@ -1,87 +0,0 @@ - - - - - fileTypes - - md - mdown - markdown - markdn - - firstLineMatch - (?i)^format:\s*complete\s*$ - foldingStartMarker - (?x) - (<(?i:head|body|table|thead|tbody|tfoot|tr|div|select|fieldset|style|script|ul|ol|form|dl)\b.*?> - |<!--(?!.*-->) - |\{\s*($|\?>\s*$|//|/\*(.*\*/\s*$|(?!.*?\*/))) - ) - foldingStopMarker - (?x) - (</(?i:head|body|table|thead|tbody|tfoot|tr|div|select|fieldset|style|script|ul|ol|form|dl)> - |^\s*--> - |(^|\s)\} - ) - keyEquivalent - ^~M - name - MultiMarkdown - patterns - - - begin - ^([A-Za-z0-9 _\-]+)(:)\s* - beginCaptures - - 1 - - name - keyword.other.multimarkdown - - 2 - - name - punctuation.separator.key-value.multimarkdown - - - end - ^$|^(?=[A-Za-z0-9]+:) - name - meta.header.multimarkdown - patterns - - - comment - The reason for not setting scopeName = "string.unquoted" - (for the parent rule) is that we do not want - newlines to be marked as string.unquoted - match - .+ - name - string.unquoted.multimarkdown - - - - - begin - ^(?!=[A-Za-z0-9]+:) - end - ^(?=not)possible$ - name - meta.content.multimarkdown - patterns - - - include - text.html.markdown.gfm - - - - - scopeName - text.html.markdown.multimarkdown - uuid - 6F5A7020-3E5F-11E3-AA6E-0800200C9A66 - - diff --git a/Markdown.sublime-settings b/Preferences.sublime-settings similarity index 52% rename from Markdown.sublime-settings rename to Preferences.sublime-settings index 8b800068..9f13252e 100644 --- a/Markdown.sublime-settings +++ b/Preferences.sublime-settings @@ -1,67 +1,58 @@ { - "extensions": - [ - "md", - "mdown", - "txt" - ], + // MarkdownEditing: + // Always keep current line vertically centered. + "mde.keep_centered": false, - "color_scheme": "Packages/MarkdownEditing/MarkdownEditor.tmTheme", - // "color_scheme": "Packages/MarkdownEditing/MarkdownEditor-Dark.tmTheme", - // "color_scheme": "Packages/MarkdownEditing/MarkdownEditor-Yellow.tmTheme", + // MarkdownEditing: + // set log level + // valid values are: "CRITICAL", "ERROR", "WARN", "INFO", "DEBUG" + "mde.logging.level": "ERROR", - // This is a quick and dirty focus theme. In order to make it work, you've to - // set `"highlight_line": true,` in this settings file. It is likely that there will - // be more mature focus improvements in the future (maybe similar to iA Writer). - // "color_scheme": "Packages/MarkdownEditing/MarkdownEditor-Focus.tmTheme", + // MarkdownEditing (Formatting): + // If `true` asterisk is used to markup bold text, underscore otherwise. + "mde.bold_marker_asterisk": true, - "tab_size": 4, - "translate_tabs_to_spaces": true, - "trim_trailing_white_space_on_save": false, - "auto_match_enabled": true, + // MarkdownEditing (Formatting): + // If `true` asterisk is used to markup italic text, underscore otherwise. + "mde.italic_marker_asterisk": false, - // Layout - "draw_centered": true, - "word_wrap": true, - "wrap_width": 80, - "rulers": [], + // MarkdownEditing (Headings): + // auto detect whether to add trailing #'s to headlines + // If `true` `mde.match_heading_hashes` is set per view depending on + // majority of first 10 headings containing trailing #'s or not. + "mde.detect_heading_style": true, - // Line - "line_numbers": false, - "highlight_line": false, - "line_padding_top": 2, - "line_padding_bottom": 2, + // MarkdownEditing (Headings): + // add trailing #'s to headlines + "mde.match_heading_hashes": false, - // Caret - "caret_style": "wide", // "wide" is deprecated starting with ST Build 3057. - // In the future, this line will be replaced with: - // "caret_style": "solid", - // "caret_extra_width": 1, - // These will work only in ST Build 3057 and later. - "caret_extra_top": 3, - "caret_extra_bottom": 3, + // MarkdownEditing (Headings): + // If `true`, trailing heading hashes are added or removed automatically, + // depending on a view's `mde.match_heading_hashes` setting value. + // + // Headings are fixed: + // a) when hitting enter at the end of a heading line + // b) after loading or before saving a file if `mde.auto_detect_match_heading_hashes` is `true`. + "mde.auto_match_heading_hashes": true, - // add trailing #'s to headlines - "mde.match_header_hashes": false, + // MarkdownEditing (Lists): + // Align list item text at indentation level. + // Adds after list items instead of a single . + "mde.list_align_text": false, + // MarkdownEditing: // Automatically switches list bullet when indenting blank list item with . "mde.list_indent_auto_switch_bullet": true, + // MarkdownEditing: // List bullets to be used for automatically switching. In their order. "mde.list_indent_bullets": ["*", "-", "+"], + // MarkdownEditing: // Auto increments ordered list number. Set to false if you want always "1". "mde.auto_increment_ordered_list_number": true, - // Always keep current line vertically centered. - "mde.keep_centered": false, - - // Distraction free mode improvements. In order for these to work, you have to install - // FullScreenStatus plugin: https://github.com/maliayas/SublimeText_FullScreenStatus - "mde.distraction_free_mode": { - "mde.keep_centered": true - }, - + // MarkdownEditing: "mde.lint": { "mdl": { // By default it is mdl.bat on windows and mdl otherwise. Leave it blank to use the default value @@ -75,20 +66,20 @@ // disabled rules, e.g. "md001". "disable": ["md013"], // Options: - // atx, ## title only - // atx_closed, ## title ## only - // setext, title only - // ===== - // any, consistent within the document + // atx, ## title only + // atx_closed, ## title ## only + // setext, title only + // ===== + // any, consistent within the document "md003": "any", // Options: - // asterisk, * only - // plus, + only - // dash, - only - // cyclic, different symbols on different levels - // and same symbol on same level - // single, same symbol on different levels - // any, same symbol on same level + // asterisk, * only + // plus, + only + // dash, - only + // cyclic, different symbols on different levels + // and same symbol on same level + // single, same symbol on different levels + // any, same symbol on same level "md004": "cyclic", // Number of spaces per list indent. Set to 0 to use Sublime tab_size instead "md007": 0, @@ -97,9 +88,9 @@ // Disallowed trailing punctuation in headers "md026": ".,;:!", // Options: - // one, '1.' only - // ordered, ascending number - // any, consistent within one list + // one, '1.' only + // ordered, ascending number + // any, consistent within one list "md029": "any", // Number of spaces after list markers depending on list type. // (ordered vs unordered, single-line vs multi-line) @@ -113,8 +104,21 @@ } }, + // MarkdownEditing (Folding): + // Enable automatic folding of url parts of inline references or images + "mde.auto_fold_link.enabled": true, + // MarkdownEditing (Folding): + // Selector for urls to automatically fold + "mde.auto_fold_link.selector": "( meta.image | meta.link ) & ( markup.underline | constant.other) - meta.link.reference.footnote - meta.link.reference.def - meta.link.inet", + + // MarkdownEditing (Wiki): + // wiki file extensions "mde.wikilinks.markdown_extension": ".md", + // MarkdownEditing (Wiki): + // wiki home page "mde.wikilinks.homepage": "HomePage", + // MarkdownEditing (Wiki): + // wiki templates "mde.wikilinks.templates": { "default_page": "templates/PageTemplate.md" }, @@ -122,13 +126,13 @@ // You can opt out some keybinds by setting the corresponding value from 'false' to 'true' (without single-quotes). // Super key references to a key next to left Alt key. It usually has a Windows logo or "win" or "Command" on it. // Jump between link/image/footnote reference and definition - // Default keys: (OSX)super+ctrl+shift+l (Linux/Win)ctrl+alt+g + // Default keys: (OSX)super+ctrl+shift+l (Linux/Win)ctrl+alt+g "mde.keymap_disable.reference_jump": false, // Add a new link - // Default keys: (OSX)super+alt+r (Linux/Win)ctrl+super+r + // Default keys: (OSX)super+alt+r (Linux/Win)ctrl+super+r "mde.keymap_disable.reference_new_reference": false, // Add a new inline link - // Default keys: (OSX)super+alt+v (Linux/Win)ctrl+super+v + // Default keys: (OSX)super+alt+v (Linux/Win)ctrl+super+v "mde.keymap_disable.reference_new_inline_link": false, // Add a new inline image // Default keys: (OSX/Linux/Win)super+shift+k @@ -136,6 +140,9 @@ // Add a new footnote // Default keys: (OSX/Linux/Win)alt+shift+6 "mde.keymap_disable.reference_new_footnote": false, + // Reorganize footnotes footnote + // Default keys: (OSX)super+ctrl+s (Linux/Win)alt+shift+s + "mde.keymap_disable.reference_organize": true, // Fold current section // Default keys: (OSX/Linux/Win)shift+tab "mde.keymap_disable.fold_section": false, @@ -143,10 +150,10 @@ // Default keys: (OSX/Linux/Win)ctrl+shift+tab "mde.keymap_disable.show_fold_all_sections": false, // Jump to the next heading (any level/same or higher level) - // Default keys: (OSX)super+ctrl/shift+pagedown (Linux/Win)ctrl+shift(+alt)+pagedown + // Default keys: (OSX)super+ctrl/shift+pagedown (Linux/Win)ctrl+shift(+alt)+pagedown "mde.keymap_disable.goto_next_heading": false, // Jump to the previous heading (any level/same or higher level) - // Default keys: (OSX)super+ctrl/shift+pageup (Linux/Win)ctrl+shift(+alt)+pageup + // Default keys: (OSX)super+ctrl/shift+pageup (Linux/Win)ctrl+shift(+alt)+pageup "mde.keymap_disable.goto_previous_heading": false, // List pages the link to the current page "mde.keymap_disable.list_back_links": true, diff --git a/README.md b/README.md index 1cffa9ba..7ea3a9bc 100644 --- a/README.md +++ b/README.md @@ -1,364 +1,114 @@ # MarkdownEditing -Markdown plugin for Sublime Text. Provides a decent Markdown color scheme (light and dark) with more __robust__ syntax highlighting and useful Markdown editing features for Sublime Text. 3 flavors are supported: Standard Markdown, __GitHub flavored Markdown__, MultiMarkdown. +**Markdown plugin for Sublime Text** -![MarkdownEditing][LightTheme] +![MarkdownEditing][preview] -[Dark][DarkTheme] and [Yellow][YellowTheme] and [ArcDark][ArcDarkTheme] theme available, plus [thirdparty themes](#additional-color-themes). See [configuration](#configuration) section to learn **how to change the theme**. +with... -## Overview +* useful Markdown editing features for Sublime Text +* color schemes optimized for writing +* robust syntax definitions for + - Standard Markdown + - Github flavored Markdown + - MultiMarkdown - - -- [Installation](#installation) - - [Package Control](#package-control) - - [Manual Installation](#manual-installation) -- [Features](#features) - - [Markdown features](#markdown-features) - - [Wiki features](#wiki-features) -- [Key Bindings](#key-bindings) -- [GFM Specific Features](#gfm-specific-features) -- [Commands for Command Palette](#commands-for-command-palette) - - [General Commands](#general-commands) - - [Links, References and Footnotes](#links-references-and-footnotes) - - [Folding and Navigation](#folding-and-navigation) -- [Configuration](#configuration) - - [Additional color themes:](#additional-color-themes) -- [Tips](#tips) -- [Enable WYSIWYG](#enable-wysiwyg) -- [Troubleshooting](#troubleshooting) - - [Error loading syntax file...](#error-loading-syntax-file) - - [Roll back to an older version](#roll-back-to-an-older-version) -- [Related Plugins](#related-plugins) -- [Known Bugs](#known-bugs) -- [Contributing](#contributing) -- [Credits](#credits) -- [Donation](#donation) -- [License](#license) - - - -## Installation - -You can install MarkdownEditing either from Package Control (recommended) or manually. Package Control automatically download the package and keeps it up-to-date. Manual installation is required if you need to tweak the code. - -If you are using Sublime Text 2, you have to disable the native package _manually_. To do that, add `Markdown` to your `ignored_packages` list in ST user settings: - - "ignored_packages": [..., "Markdown"], - -> Getting "Error loading syntax file..."? See [this](#error-loading-syntax-file). - -### Package Control - -The preferred method of installation is via [Sublime Package Control][PackageControl]. - -1. [Install Sublime Package Control][InstallPackageControl] -2. From inside Sublime Text, open Package Control's Command Pallet: CTRL SHIFT P (Windows, Linux) or CMD SHIFT P on Mac. -3. Type `install package` and hit Return. A list of available packages will be displayed. -4. Type `MarkdownEditing` and hit Return. The package will be downloaded to the appropriate directory. -5. Restart Sublime Text to complete installation. Open a Markdown file and this custom theme. The features listed below should now be available. - -### Manual Installation - -1. In Sublime Text, open the menu "Preferences" -> "Browse Packages...". This is the Sublime Text Packages directory. -2. [Download and unzip](https://github.com/SublimeText-Markdown/MarkdownEditing/archive/master.zip) or [clone](https://help.github.com/articles/cloning-a-repository/) this repository to a directory `MarkdownEditing` in the Sublime Text Packages directory. -3. The folder structure should look like `.../Sublime Text 3/Packages/MarkdownEditing/[files]`. -4. Restart Sublime Text to complete installation. Open a Markdown file. The features listed below should now be available. +Please visit [User Guide][UserGuide] to learn more about the full set of features and how to use them. ## Features -You can access most features through Command Palette. You can launch it from `Tools -> Command Palette...`. MarkdownEditing commands start with `MarkdownEditing:`. And they are only visible when a markdown file is open and active. - -### Markdown features - -* __Pairing__ - - Asterisks and underscores are autopaired and will wrap selected text. - - If you start an empty pair and hit backspace, both elements are deleted. - - If you start an empty pair and hit space, the right element is deleted. - - Backticks are paired. So entering `` ` `` will expand to `` `(cursor here)` ``. -* __List__ - - At the end of a list item, pressing Enter will automatically insert the new list item bullet. - - Pressing Tab on the blank list item will indent it and switch the list bullet to another one (Order is `*`, `-`, `+` in a cycle). - - Pressing Shift Tab on the blank list item will unindent it in the same way as above. - - Sequential Tab s or Shift Tab s are supported. - - You can disable automatic bullet switching or choose which bullets to be used, in your settings file (`mde.list_indent_bullets`). - - If a list item contains a [GFM task][], pressing Enter at the end of the line will continue with a new blank task. -* __Blockquote__ - - At the end of a blockquote line, pressing Enter will automatically extend blockquote. - - Selecting some text and pressing > will convert it to blockquote. The first and the last line don't have to be fully selected; partial select works, too. -* __Link__ - - Left bracket pairing is modified to eliminate the selection and leave the cursor at a point where you can insert a `[]` or `()` pair for a link. - - If you leave the cursor on a link, you can right click and jump between reference and url. -* __Navigation__ - - Displays Markdown headers in the Project Symbol List (`Goto -> Goto Symbol in Project...`). They will start with `#`, so you will know they belong to markdown files at a glance. Also they will be on top of the list because of the precedence of `#`. - - Headers also appear in Document Symbol List (`Goto -> Goto Symbol...`) - - You can fold current section with Ctrl Tab - - You can navigate between adjacent headers with `Find Next(Previous) Heading` command. -* __Strikethrough__ - - ~ wraps selected text with `~~` (strikethrough). When you for instance select the word "foo" and hit `~`, the result will be `~~foo~~`. -* __Header__ - - Typing `#` when there's a selection will surround it with `#` to make it a headline. Multiple presses add additional hashes, increasing the level of the header. Once you hit 6 hashes, it will reset to 0 on the next press. The `mde.match_header_hashes` will determine if the `#` are mirrored on both sides or just at the beginning of the line. - - Typing return at the end of a line that begins with hashmarks will insert closing hashmarks on the headline. They're not required for Markdown, it's just aesthetics, and you can change the `mde.match_header_hashes` option in your settings to enable (disabled by default). - - Setext-style headers can be completed with `Tab`. That is, typing `Tab` on a line containing only `=` or `-` characters will add or remove enough characters to it to match the length of the line above. - - New documents will be named automatically based on the first header. - -### Wiki features - -Wiki links are defined by surrounding a (wiki) word with double square brackets, for example: - - [[SampleWikiPage]] - -The user can `open` wiki page using a sublime command. This will search the current open file's directory (and sub-directories) for a file with a matching name and a markdown extension. For example, opening the previous wiki link -will look for and open a file named: - - SampleWikiPage.md - -Note that, if the wiki page does *not* yet exist, if will be created with a header matching the page name. However the file will only actually be created on the file system, when it is saved by the user. - -The user can `list back links` and of course to open them. Back links are pages that reference the current page. This allows pages to be tied together into a personal wiki. A common technique is to define *tag* wiki pages and to list any tags for a page as references to the tag pages at the bottom of the page, for example: - - [[TagSyntax]] [[TagDev]] [[TagPython]] - -This allows the user to list all pages with a specific tag, by opening the tag page and list all back links. - -Journal wiki pages are also supported. A journal page is just a wiki page with a name matching the current date. - -Lastly the command to open the *home* page is provided, where the home page is just a wiki page named `HomePage`. - -## Key Bindings - -| OS X | Windows/Linux | Description | -|------|---------------|-------------| -| V | CtrlAltV | Creates or pastes the contents of the clipboard as an inline link on selected text. -| R | CtrlAltR | Creates or pastes the contents of the clipboard as a reference link. -| K | ShiftWinK | Creates or pastes the contents of the clipboard as an inline image on selected text. -| B I | AltB AltI | These are bound to bold and italic. They work both with and without selections. If there is no selection, they will just transform the word under the cursor. These keybindings will unbold/unitalicize selection if it is already bold/italic. -| ^1...6 | Ctrl1...6 | These will add the corresponding number of hashmarks for headlines. Works on blank lines and selected text in tandem with the above headline tools. If you select an entire existing headline, the current hashmarks will be removed and replaced with the header level you requested. This command respects the `mde.match_header_hashes` preference setting. -| 6 | AltShift6 | Inserts a footnote. -| Tab | ShiftTab | Fold/Unfold current section. -| ^Tab | CtrlShiftTab | Fold all sections under headings of a certain level. -| PageUp PageDown | CtrlAltShiftPageUp CtrlAltShiftPageDown | Go to the previous/next heading of the same or higher level -| PageUp PageDown | CtrlShiftPageUp CtrlShiftPageDown | Go to the previous/next heading -| H | CtrlShiftH | Open home page -| D | CtrlShiftD | Open wiki page under the cursor -| J | CtrlShiftJ | Open journal page for today -| B | CtrlShiftB | List back links - - -## GFM Specific Features - -[GFM][] means GitHub Flavored Markdown is the dialect of Markdown that is currently supported for user content on GitHub.com and GitHub Enterprise. It has [some unique features][GFMFeatures]: - -Underscores in words doesn't mess with bold or italic style: - -![underscore-in-words][GFM-UnderscoreInWords] - -Fenced code blocks gets syntax highlighting inside: - -![fenced-code-block][GFM-FencedCodeBlock] - -Keyboard shortcuts gets highlighted like in GitHub: - -![keyboard-shortcut][GFM-KeyboardShortcut] - -Strikethrough is supported: - -![strikethrough][GFM-Strikethrough] - -## Commands for Command Palette - -You can launch Command Palette from `Tools -> Command Palette...`. MarkdownEditing commands start with `MarkdownEditing:`. And they are only visible when a markdown file is open and active. - -### General Commands - -* __Fix Underlined Headers__ - Adjusts every setext-style header to add or remove `=` or `-` characters as needed to match the lengths of their header text. -* __Convert Underlined Headers to ATX__ - Converts every setext-style header into an ATX style header. If something is selected only the headers in the selections will be converted, otherwise the conversion will be applied to the whole view. -* __Markdown Lint__ - Performs lint on current Markdown file using a local linter. See [lint rules](lint_docs/RULES.md). Some of the linting rules are customizable via user settings file. -* __Run markdownlint__ - Run mdl command from [markdownlint](https://github.com/markdownlint/markdownlint) package. You need to install it by yourself. -* __Change color scheme...__ - Lists built-in Markdown color schemes for you to preview and use. -* __Switch List Bullet Type__ - Switches the highlighted list between numbered and bulleted style. - -### Links, References and Footnotes - -* __Add Missing Link Labels__ - Scans document for referenced link usages (`[some link][some_ref]` and `[some link][]`) and checks if they are all defined. If there are undefined link references, command will automatically create their definition snippet at the bottom of the file. -* __Magic Footnotes Command__ - Adds a footnote after the word under cursor. If cursor is already on a footnote, jumps to its definition or reference. -* __Gather Missing Footnotes__ - Add definition stubs (if there is none) for all footnotes references. -* __Jump Reference__ - Jumps cursor between definitions and references. -* __New Reference__ - Adds a new link under cursor. -* __New Inline Link__ - Adds a new inline link under cursor. -* __New Inline Image__ - Adds a new inline image under cursor. -* __New Image__ - Adds a new image under cursor. -* __New Footnote__ - Adds a footnote under cursor. -* __Delete Reference__ - Deletes the definition and references of a link. -* __Organize References__ - Sorts and gives a report on current link references usage. - ### Folding and Navigation -Remeber you can Ctrl R (in document) and Ctrl Shift R (project-wise) for quick navigation for all headers. - -* __Toggle Folding Current Section__ - Folds/unfolds current section. -* __Fold Level 1-4 Sections__ - Fold all sections under headers of specific level. -* __Fold/Unfold All Sections__ - Self explanatory. -* __Find Next/Previous Heading__ - You have option to find just same or higher level or any level - -## Configuration - -The plugin contains 3 different Markdown flavors: Standard Markdown, GitHub flavored Markdown, MultiMarkdown. Default is GitHub flavored Markdown. If you want to set another one as default, open a Markdown file and select your flavor from the menu: `View > Syntax > Open all with current extension as`. You're done. - -You may want to have a look at the default settings files. They are located at: - - Packages/MarkdownEditing/Markdown.sublime-settings [GitHub flavored Markdown] - Packages/MarkdownEditing/Markdown (Standard).sublime-settings - Packages/MarkdownEditing/MultiMarkdown.sublime-settings - -If you want to override any of the default settings, you can open the appropriate user settings file using the `Preferences > Package Settings > Markdown Editing` menu. Each flavor has a different settings file. - -Bold and italic markers are configurable through ST shell variables. You can use `Preferences > Package Settings > Markdown Editing` menu to see the default settings file. In order to override it, copy & paste its content into the user settings file (`Packages/User/Bold and Italic Markers.tmPreferences`) from the menu and make your edits. It is pretty straightforward. - -In order to activate the dark or the yellow theme, put one of these lines to your user settings file of the flavor (`Packages/User/[flavor].sublime-settings`): +* displays headings in _Goto Symbol..._ +* displays headings in _Goto Symbol in Project..._ +* fold current section +* fold by heading levels +* navigate between adjacent headings with `Find Next/Previous Heading` command. - "color_scheme": "Packages/MarkdownEditing/MarkdownEditor-Dark.tmTheme", - "color_scheme": "Packages/MarkdownEditing/MarkdownEditor-Yellow.tmTheme", - "color_scheme": "Packages/MarkdownEditing/MarkdownEditor-ArcDark.tmTheme", - +### Headings -If you want to go with your already existing theme, you can reenable it with the same method as above. Keep in mind that, that theme may not cover all the parts of the Markdown syntax that this plugin defines. +* automatic detection and maintenance of open or closed [atx headings][AtxHeadings] style while typing +* change [headings levels][HeadingsLevels] via key bindings +* auto-complete [Setext-style headings][SeHeadings] underlines +* convert [Setext-style headings][SeHeadings] to ATX headings +* new documents are named automatically based on first header -### Additional color themes: +### Lists -- [Blackboard theme][linkBlackboardTheme] by [@mdesantis][mdesantis] -- [monokaiC](https://github.com/avivace/monokaiC) by [@avivace][avivace] +* At the end of a list item, pressing Enter will automatically insert the new list item bullet. +* Pressing Tab on the blank list item will indent it and switch the list bullet to another one (Order is `*`, `-`, `+` in a cycle). +* Pressing Shift + Tab on the blank list item will unindent it in the same way as above. +* Sequential Tab s or Shift Tab s are supported. +* You can disable automatic bullet switching or choose which bullets to be used, in your settings file (`mde.list_indent_bullets`). +* If a list item contains a [GFM Task][], pressing + - Enter at the end of the line continues with a new blank task. + - Alt+X in the line toggles the check mark. -By default, when you install the plugin, files with these extensions will be assigned to Markdown syntax: "md", "txt", "mdown", "markdown", "markdn". If you want to prevent any of these extensions to be opened as Markdown, follow these steps: +### Blockquotes -1. Click on the language menu at bottom right -2. Select "Open all with current extension as" -3. Choose your preferred syntax for that extension +* At the end of a blockquote line, pressing Enter will automatically extend blockquote. +* Selecting some text and pressing > will convert it to blockquote. The first and the last line don't have to be fully selected; partial select works, too. -## Tips +### Critic Markup -We are maintaining a [tips section][tips] in our [Wiki][]. Jump there to learn from others or share your experiences with others. +* Syntax highlighting for inline critic markup + - `{++ addition ++}` + - `{>> comment <<}` + - `{-- deletion --}` + - `{== highlight==}{>> comment <<}` + - `{~~ substitution ~> by ~~}` +* Reviewers can add critic via key bindings +* Authors can accept or reject critic via key bindings -## Enable WYSIWYG +### Links and References -Sublime can be configured into a WYSIWYG (what you see is what you get) editor with two other plugins: +* Left bracket pairing is modified to eliminate the selection and leave the cursor at a point where you can insert a `[]` or `()` pair for a link. +* URL part of images, links and references is automatically folded if caret is not within brackets +* Convert inline links to references +* Jump between definitions and references +* Organize references +* Add or remove footnotes -1. Markdown Preview (https://packagecontrol.io/packages/Markdown%20Preview) -1. Livereload (https://packagecontrol.io/packages/LiveReload) +### Text Formatting -Install them if you haven't. Then - -1. Open Palette -1. LiveReload: Enable/Disable Plugins -1. Enable Simple Reload. - -Now open palette and choose "Preview in Browser" and you will get a WYSIWYG editor. - -## Troubleshooting - -### Error loading syntax file... - -__Are you getting this error after installation: _**Error loading syntax file** "Packages/Markdown/Markdown.tmLanguage": Unable to open Packages/Markdown/Markdown.tmLanguage_?__ - -> This is caused by open markdown files at the install time. You have to __manually change their syntax to your newly installed Markdown syntax__. Read the below paragraph for more details on this. - -_Note_: Sublime text has a native tiny package for Markdown. However, when MarkdownEditing is enabled, native package causes some conflicts. For this reason, MarkdownEditing will automatically disable it. Since it doesn't bring anything new over MarkdownEditing, this is not a loss. But remember, when you disable MarkdownEditing, you have to reenable the native one manually (if you want). - -### Roll back to an older version - -When you notice any undesired behavior introduced by the latest update, your feedback is always welcome in our [issue page](https://github.com/SublimeText-Markdown/MarkdownEditing/issues). However before it's fixed, you can rollback to [an earlier version](https://github.com/SublimeText-Markdown/MarkdownEditing/releases). Find the desired version and download the zip file, then follow [manual installation guide](#manual-installation) - -## Related Plugins - -* [Knockdown][] - - Knockdown offers useful Markdown features and a custom Markdown theme. All of its unique features except its theme are ported to MarkdownEditing and some of them are actually improved further in MarkdownEditing. -* [Sublime Markdown Extended][] -* [SmartMarkdown][] -* [MarkdownTOC][] - - Sublime Text 3 plugin for generating a Table of Contents (TOC) in a Markdown document. -* See https://packagecontrol.io/search/markdown for more. - -## Known Bugs - -* Setext-style headers (`===` and `---`) do not show up in the symbol list. This is due to a Sublime Text limitation (see [#158][]). However, we are able to put a placeholder to indicate the existence of the header. We encourage you to use Atx-style headers (`#`). - -* Installing for the first time while having markdown files opened may cause MarkdownEditing to behave unexpectedly on those files. Close and reopen those files to fix it. +* Asterisks (\*), backticks (\`) and underscores (\_) are auto-paired and wrap selected text +* ~ wraps selected text with `~~` (strike-through) +* Backspace deletes an empty pair +* Space or Tab deletes right element of empty pair of asterisks or underscores ## Contributing -See `CONTRIBUTING.md` file. +See [CONTRIBUTING.md](CONTRIBUTING.md). ## Credits -MarkdownEditing was originally created by [Brett Terpstra][brettterpstra] and has become a community project with the goal of consolidating the best features from the varied collection of Markdown packages for Sublime Text. Current development is headed up by [Ali Ayas][maliayas] and [Felix Hao][felixhao28]. +MarkdownEditing was originally created by [Brett Terpstra][] and has become a community project with the goal of consolidating the best features from the varied collection of Markdown packages for Sublime Text. Current development is headed up by [Ali Ayas][] and [Felix Hao][]. Related blog posts from Brett: -* http://brettterpstra.com/2012/05/17/markdown-editing-for-sublime-text-2-humble-beginnings/ -* http://brettterpstra.com/2013/11/23/markdownediting-for-sublime-text-updates/ - -This plugin contains portions of code from [Knockdown][]. -Footnote commands were submitted by [J. Nicholas Geist][] and originated at [geekabouttown][geekabouttown]. +* http://brettterpstra.com/2012/05/17/markdown-editing-for-sublime-text-2-humble-beginnings +* http://brettterpstra.com/2013/11/23/markdownediting-for-sublime-text-updates -## Donation - -You can support [contributors](https://github.com/SublimeText-Markdown/MarkdownEditing/graphs/contributors) of this project individually. Every contributor is welcomed to add his/her line below with any content. Ordering shall be alphabetically by GitHub username. +This plugin contains portions of code from [Knockdown][]. -* [@felixhao28][felixhao28]: [paypal] -* [@maliayas][maliayas]: [paypal] ![donation received](http://maliayas.com/business/donation/badge.php?project=markdown_editing) +Footnote commands were submitted by [J. Nicholas Geist][] and originated at [geekabouttown][]. ## License MarkdownEditing is released under the [MIT License][opensource]. -[LightTheme]: https://raw.github.com/SublimeText-Markdown/MarkdownEditing/master/screenshots/light.png -[DarkTheme]: https://raw.github.com/SublimeText-Markdown/MarkdownEditing/master/screenshots/dark.png -[YellowTheme]: https://raw.github.com/SublimeText-Markdown/MarkdownEditing/master/screenshots/yellow.png -[ArcDarkTheme]: https://raw.github.com/SublimeText-Markdown/MarkdownEditing/master/screenshots/arcdark.png -[PackageControl]: http://wbond.net/sublime_packages/package_control -[InstallPackageControl]: http://wbond.net/sublime_packages/package_control/installation -[GFM task]: https://github.github.com/gfm/#task-list-items-extension- -[GFM]: https://github.github.com/gfm/ -[GFMFeatures]: https://guides.github.com/features/mastering-markdown/ -[GFM-UnderscoreInWords]: https://raw.github.com/SublimeText-Markdown/MarkdownEditing/master/screenshots/underscore-in-words.png -[GFM-FencedCodeBlock]: https://raw.github.com/SublimeText-Markdown/MarkdownEditing/master/screenshots/fenced-code-block.png -[GFM-KeyboardShortcut]: https://raw.github.com/SublimeText-Markdown/MarkdownEditing/master/screenshots/keyboard-shortcut.png -[GFM-Strikethrough]: https://raw.github.com/SublimeText-Markdown/MarkdownEditing/master/screenshots/strikethrough.png -[linkBlackboardTheme]: https://github.com/mdesantis/MarkdownEditing/blob/blackboard-theme/MarkdownEditor-Blackboard.tmTheme -[mdesantis]: https://github.com/mdesantis -[avivace]: https://github.com/avivace -[tips]: https://github.com/SublimeText-Markdown/MarkdownEditing/wiki/Tips -[Wiki]: https://github.com/SublimeText-Markdown/MarkdownEditing/wiki -[Knockdown]: https://github.com/aziz/knockdown/ -[Sublime Markdown Extended]: https://github.com/jonschlinkert/sublime-markdown-extended -[SmartMarkdown]: https://github.com/demon386/SmartMarkdown -[MarkdownTOC]: https://github.com/naokazuterada/MarkdownTOC -[#158]: https://github.com/SublimeText-Markdown/MarkdownEditing/issues/158 -[brettterpstra]: http://brettterpstra.com -[maliayas]: https://github.com/maliayas -[felixhao28]: https://github.com/felixhao28 -[J. Nicholas Geist]: https://github.com/jngeist + +[preview]: docs/img/preview.png +[Knockdown]: https://github.com/aziz/knockdown [geekabouttown]: http://geekabouttown.com/posts/sublime-text-2-markdown-footnote-goodness [opensource]: http://www.opensource.org/licenses/MIT +[UserGuide]: https://sublimetext-markdown.github.io/MarkdownEditing +[AtxHeadings]: docs/usage.md#atx-style +[HeadingsLevels]: docs/usage.md#headings-levels +[SeHeadings]: docs/usage.md#setext-style +[GFM Task]: https://github.github.com/gfm/#task-list-items-extension- + +[Ali Ayas]: https://github.com/maliayas +[Brett Terpstra]: http://brettterpstra.com +[Felix Hao]: https://github.com/felixhao28 +[J. Nicholas Geist]: https://github.com/jngeist diff --git a/bootstrap.py b/bootstrap.py deleted file mode 100644 index aafaf61f..00000000 --- a/bootstrap.py +++ /dev/null @@ -1,158 +0,0 @@ -import sys -import sublime -import sublime_plugin -import re -try: - from MarkdownEditing.mdeutils import * -except ImportError: - from mdeutils import * - -package_name = 'MarkdownEditing' - - -def get_ingored_packages(): - settings = sublime.load_settings('Preferences.sublime-settings') - return settings.get('ignored_packages', []) - - -def save_ingored_packages(ignored_packages): - settings = sublime.load_settings('Preferences.sublime-settings') - settings.set('ignored_packages', ignored_packages) - sublime.save_settings('Preferences.sublime-settings') - - -def disable_native_markdown_package(): - ignored_packages = get_ingored_packages() - if 'Markdown' not in ignored_packages: - ignored_packages.append('Markdown') - save_ingored_packages(ignored_packages) - - -def enable_native_markdown_package(): - ignored_packages = get_ingored_packages() - if 'Markdown' in ignored_packages: - ignored_packages.remove('Markdown') - save_ingored_packages(ignored_packages) - - -def choose_color_theme(window=None): - window = window or sublime.active_window() - view = window.new_file() - view.run_command('append', {'characters': '''# A sample Markdown document - -This is a sample document so you can preview the color themes. - -## I am a second-level header - -Markdown supports _italics_, __bold__, and ___bold italics___ style. - -There are also inline styles like `inline code in monospace font` and ~~strikethrough style~~. __There may be ~~strikethroughed text~~ or `code text` inside bold text.__ _And There may be ~~strikethroughed text~~ or `code text` inside italic text._ - -To reference something from a URL, [Named Links][links] and [Inline links](https://example.com/index.html) are of great help. Sometimes ![A picture][sample image] is worth a thousand words. - -There are two types of lists, numbered and unnumbered. - -1. Item 1 -2. Item 2 -3. Item 3 - -* Item A - - Sub list - + Sub sub list - + Sub sub list 2 - - Sub list 2 -* Item B -* Item C - -## Fenced code - -You can write fenced code inside three backticks. - -```javascript -function fibo(n) { - fibo.mem = fibo.mem || []; // I am some comment - return fibo.mem[n] || fibo.mem[n] = n <= 1 ? 1 : fibo(n - 1) + fibo(n - 2); -} -``` - -## The following section is used to define named links - -[links]: https://example.com/index.html -[sample image]: https://example.com/sample.png - -## Wiki links - -This [[SamplePage]] is a wiki link - ---- - -'''}) - view.set_syntax_file('Packages/MarkdownEditing/Markdown.tmLanguage') - default_mde_scheme = sublime.load_settings('Markdown.sublime-settings').get('color_scheme') or 'Packages/MarkdownEditing/MarkdownEditor.tmTheme' - print(default_mde_scheme) - view.settings().set('color_scheme', default_mde_scheme) - view.set_read_only(True) - view.set_scratch(True) - - global_scheme = sublime.load_settings('Preferences.sublime-settings').get('color_scheme') - themes = ['Packages/MarkdownEditing/MarkdownEditor.tmTheme', - 'Packages/MarkdownEditing/MarkdownEditor-Focus.tmTheme', - 'Packages/MarkdownEditing/MarkdownEditor-Yellow.tmTheme', - 'Packages/MarkdownEditing/MarkdownEditor-Dark.tmTheme', - 'Packages/MarkdownEditing/MarkdownEditor-ArcDark.tmTheme', - global_scheme] - - themes_display = [re.search('[^/]+(?=\.tmTheme$)', s).group(0) + (' (Current)' if s == default_mde_scheme else '') + (' (Global)' if s == global_scheme else '') for s in themes] - - def set_scheme(scheme): - view.settings().set('color_scheme', scheme) - sublime.load_settings('Markdown.sublime-settings').set('color_scheme', scheme) - - def on_done(index): - if index == -1: - set_scheme(default_mde_scheme) - elif index == len(themes) - 1: - set_scheme(global_scheme) - else: - set_scheme(themes[index]) - sublime.save_settings('Markdown.sublime-settings') - view.close() - - def on_highlighted(index): - if index == len(themes) - 1: - set_scheme(global_scheme) - else: - set_scheme(themes[index]) - - window.show_quick_panel(themes_display, on_done, flags=sublime.KEEP_OPEN_ON_FOCUS_LOST, on_highlight=on_highlighted) - - -def plugin_loaded(): - if "package_control" in sys.modules: - from package_control import events - - if events.install(package_name): - # Native package causes some conflicts. - disable_native_markdown_package() - # Prmopts to select a color theme - choose_color_theme() - - -def plugin_unloaded(): - if "package_control" in sys.modules: - from package_control import events - - if events.remove(package_name): - # Native package causes some conflicts. - enable_native_markdown_package() - -# Compat with ST2 -if sys.version_info < (3,): - plugin_loaded() - unload_handler = plugin_unloaded - - -class MdeColorActivateCommand(MDETextCommand): - - def run(self, edit): - choose_color_theme(self.view.window()) diff --git a/custom_find_under_expand.py b/custom_find_under_expand.py deleted file mode 100644 index 8a363150..00000000 --- a/custom_find_under_expand.py +++ /dev/null @@ -1,22 +0,0 @@ -""" - Re-implements `find_under_expand` command because ST refuses to use it inside macro - definitions. - - Source: http://www.sublimetext.com/forum/viewtopic.php?f=3&t=5148 -""" - -import sublime -import sublime_plugin - - -class CustomFindUnderExpandCommand(sublime_plugin.TextCommand): - - def run(self, edit): - regions = [] - - for s in self.view.sel(): - word = self.view.word(sublime.Region(s.begin(), s.end())) - regions.append(word) - - for r in regions: - self.view.sel().add(r) diff --git a/decide_title.py b/decide_title.py deleted file mode 100644 index 664691f5..00000000 --- a/decide_title.py +++ /dev/null @@ -1,32 +0,0 @@ -import sublime -import sublime_plugin -import re - - -class DecideTitle(sublime_plugin.EventListener): - - def on_modified_async(self, view): - syntax = view.settings().get('syntax') - if syntax and 'Markdown' in syntax: - text = view.substr(sublime.Region(0, view.size())) - it = re.finditer(r'^(#{1,6}(?!#))|^(-{3,}|={3,})', text, re.M) - title = '' - title_begin = None - for m in it: - if '.front-matter' in view.scope_name(m.start()): - continue - if re.match(r'^(-{3,}|={3,})$', m.group()): - title_end = m.start() - 1 - title_begin = text.rfind('\n', 0, title_end) + 1 - else: - title_begin = m.end() - title_end = re.search('(' + m.group() + ')?(\n|$)', text[title_begin:]).start() + title_begin - title_begin = m.start() + 1 - if 'markup.raw.block.markdown' not in view.scope_name(title_begin).split(' '): - break - if len(title) == 0 and title_begin is not None: - title = text[title_begin: title_end] - - title = title.strip() - if view.file_name() is None and len(title) > 0: - view.set_name(title[:55]) diff --git a/distraction_free_mode.py b/distraction_free_mode.py deleted file mode 100644 index 662dc82e..00000000 --- a/distraction_free_mode.py +++ /dev/null @@ -1,34 +0,0 @@ -""" - This file contains some "distraction free" mode improvements. However they can be - used in normal mode, too. These features can be enabled/disabled via settings files. - In order to target "distraction free" mode, FullScreenStatus plugin must be installed: - https://github.com/maliayas/SublimeText_FullScreenStatus -""" - -import sublime -import sublime_plugin -try: - from MarkdownEditing.mdeutils import * -except ImportError: - from mdeutils import * - - -def on_distraction_free(): - return sublime.active_window().settings().get('fss_on_distraction_free') - - -class KeepCurrentLineCentered(sublime_plugin.EventListener): - - def on_modified_async(self, view): - # One of the MarkdownEditing syntax files must be in use. - if not view_is_markdown(view): - return False - - if on_distraction_free(): - if not view.settings().get('mde.distraction_free_mode', {}) \ - .get('mde.keep_centered', True): - return False - elif not view.settings().get('mde.keep_centered', False): - return False - - view.show_at_center(view.sel()[0].begin()) diff --git a/docs/config.md b/docs/config.md new file mode 100644 index 00000000..4a2736ca --- /dev/null +++ b/docs/config.md @@ -0,0 +1,68 @@ +# Configuration + +Default MarkdownEditing related configuration is located in _Preferences.sublime-settings_ as of version 3.0.0 to take full advantage of [settings file loading hierarchies](https://www.sublimetext.com/docs/settings.html#settings_files). + +It means you can specify + +* global preferences which apply to all Markdown flavours in `Preferences.sublime-settings` +* project specific settings in your `[Project].sublime-project` +* syntax specific settings for a certain Markdown flavour in `[Syntax Name].sublime-settings` +* settings for distraction free mode in `Distraction Free.sublime-settings` + +All MarkdownEditing related settings are prefixed with `mde.`. + +!!!note "Migration Note" + You may need or want to clean up existing syntax specific settings. + + _MarkdownEditing no longer modifies visual settings such as caret width or line paddings._ + +## Change Configuration + +Configuration can be modified via main menu and Command Palette. Using the following commands displays default MarkdownEditing settings on the left and your user preferences on the right. + +* In _Main Menu_ navigate to: `Preferences > Package Preferences > MarkdownEditing` +* In _Command Palette_ look for: `Preferences: MarkdownEditing ...` + +!!!note "Package Recommendation" + [PackageDev](https://packagecontrol.io/packages/PackageDev) may assist you by providing auto-completion for known preferences. + +## Change Color Scheme + +You can use your global color scheme or one of those shipped with MarkdownEditing for working in Markdown. To change color scheme: + +1. Open Command Palette (Ctrl + Shift + P for Windows/Linux, Cmd + Shift + P for Mac OS) +3. Search for _MarkdownEditing: Select Color Scheme_ and hit Enter. +4. Choose color scheme and press Enter. + +#### Additional Color Schemes: + +- [Blackboard theme](linkBlackboardTheme) by [@mdesantis](https://github.com/mdesantis) +- [monokaiC](https://github.com/avivace/monokaiC) by [@avivace](https://github.com/avivace) + +!!!note "Custom Color Schemes" + MarkdownEditing lists all color schemes named like `MarkdownEditor-.sublime-color-scheme`, no matter which package they are placed in. + +## Assigning Syntax + +The following file extensions are assigned with Markdown by default: `*.md`, `*.mdown`, `*.markdn`, `*.markdown`. If you want to prevent any of these extensions to be opened as Markdown or assign them another Markdown flavour: + +1. Click on the language menu at bottom right of statusbar +2. Select _Open all with current extension as_ +3. Choose your preferred syntax for that extension + +or use main menu `View > Syntax > Open all with current extension as`. + +## Markdown Preview + +MarkdownEditing doesn't provide functions to preview or convert markdown to HTML. Automatic preview can be achieved with both of: + +1. [Markdown Preview](https://packagecontrol.io/packages/Markdown%20Preview) +2. [Livereload](https://packagecontrol.io/packages/LiveReload) + +Install them if you haven't. Then + +1. Open Command Palette (Ctrl + Shift + P for Windows/Linux, Cmd + Shift + P for Mac OS) +2. Search for _LiveReload: Enable/Disable Plugins_ +3. Enable Simple Reload. +4. Open Command Palette again +5. Search for _Markdown Preview: Preview in Browser_ diff --git a/docs/css/styles.css b/docs/css/styles.css new file mode 100644 index 00000000..bc5090ec --- /dev/null +++ b/docs/css/styles.css @@ -0,0 +1,9 @@ +h1 { + font-weight: 300; + border-bottom: solid 1px #eee; + padding: 2rem 0 1rem 0; +} + +h2 { + font-weight: 300; +} diff --git a/docs/img/dev/Unbenannt.xcf b/docs/img/dev/Unbenannt.xcf new file mode 100644 index 00000000..ad3dc854 Binary files /dev/null and b/docs/img/dev/Unbenannt.xcf differ diff --git a/docs/img/dev/Unbenannt2.xcf b/docs/img/dev/Unbenannt2.xcf new file mode 100644 index 00000000..a01e6aa1 Binary files /dev/null and b/docs/img/dev/Unbenannt2.xcf differ diff --git a/docs/img/headings-setext.png b/docs/img/headings-setext.png new file mode 100644 index 00000000..336fa7bb Binary files /dev/null and b/docs/img/headings-setext.png differ diff --git a/docs/img/preview.png b/docs/img/preview.png new file mode 100644 index 00000000..2b5a06a6 Binary files /dev/null and b/docs/img/preview.png differ diff --git a/docs/img/theme-arcdark.png b/docs/img/theme-arcdark.png new file mode 100644 index 00000000..b430c199 Binary files /dev/null and b/docs/img/theme-arcdark.png differ diff --git a/docs/img/theme-dark.png b/docs/img/theme-dark.png new file mode 100644 index 00000000..927f0fbc Binary files /dev/null and b/docs/img/theme-dark.png differ diff --git a/docs/img/theme-light.png b/docs/img/theme-light.png new file mode 100644 index 00000000..0a979d3a Binary files /dev/null and b/docs/img/theme-light.png differ diff --git a/docs/img/theme-mariana.png b/docs/img/theme-mariana.png new file mode 100644 index 00000000..d22c60b3 Binary files /dev/null and b/docs/img/theme-mariana.png differ diff --git a/docs/img/theme-yellow.png b/docs/img/theme-yellow.png new file mode 100644 index 00000000..8b5ce4dc Binary files /dev/null and b/docs/img/theme-yellow.png differ diff --git a/docs/index.md b/docs/index.md new file mode 100644 index 00000000..bd19e327 --- /dev/null +++ b/docs/index.md @@ -0,0 +1,93 @@ +# MarkdownEditing + +**Markdown plugin for Sublime Text** + +![MarkdownEditing][preview] + +with... + +* useful Markdown editing features for Sublime Text +* color schemes optimized for writing +* robust syntax definitions for + * Standard Markdown + * Github flavoured Markdown + * MultiMarkdown + +ⓘ _See [configuration][] section to learn how to change the color scheme_. + +!!!note "Most features are available through Command Palette." + + 1. Open Command Palette ctrl + shift + P (Windows, Linux) + or + + P (on Mac) + 2. Type `MarkdownEditing:` to display a list of available commands. + + ⓘ _They are only visible if a markdown file is open and focused._ + +## Features + +### Folding and Navigation + +* displays headings in _Goto Symbol..._ +* displays headings in _Goto Symbol in Project..._ +* fold current section +* fold by heading levels +* navigate between adjacent headings with `Find Next/Previous Heading` command. + +### Headings + +* automatic detection and maintenance of open or closed [atx headings][AtxHeadings] style while typing +* change [headings levels][HeadingsLevels] via key bindings +* auto-complete [Setext-style headings][SeHeadings] underlines +* convert [Setext-style headings][SeHeadings] to ATX headings +* new documents are named automatically based on first header + +### Lists + +* At the end of a list item, pressing Enter will automatically insert the new list item bullet. +* Pressing Tab on the blank list item will indent it and switch the list bullet to another one (Order is `*`, `-`, `+` in a cycle). +* Pressing Shift + Tab on the blank list item will unindent it in the same way as above. +* Sequential Tab s or Shift Tab s are supported. +* You can disable automatic bullet switching or choose which bullets to be used, in your settings file (`mde.list_indent_bullets`). +* If a list item contains a [GFM Task][], pressing + - Enter at the end of the line continues with a new blank task. + - Alt+X in the line toggles the check mark. + +### Blockquotes + +* At the end of a blockquote line, pressing Enter will automatically extend blockquote. +* Selecting some text and pressing > will convert it to blockquote. The first and the last line don't have to be fully selected; partial select works, too. + +### Critic Markup + +* Syntax highlighting for inline critic markup + - `{++ addition ++}` + - `{>> comment <<}` + - `{-- deletion --}` + - `{== highlight==}{>> comment <<}` + - `{~~ substitution ~> by ~~}` +* Reviewers can add critic via key bindings +* Authors can accept or reject critic via key bindings + +### Links and References + +* Left bracket pairing is modified to eliminate the selection and leave the cursor at a point where you can insert a `[]` or `()` pair for a link. +* URL part of images, links and references is automatically folded if caret is not within brackets +* Convert inline links to references +* Jump between definitions and references +* Organize references +* Add or remove footnotes + +### Text Formatting + +* Asterisks (\*), backticks (\`) and underscores (\_) are auto-paired and wrap selected text +* ~ wraps selected text with `~~` (strike-through) +* Backspace deletes an empty pair +* Space or Tab deletes right element of empty pair of asterisks or underscores + + +[preview]: img/preview.png +[configuration]: config.md#change-color-scheme +[AtxHeadings]: usage.md#atx-style +[HeadingsLevels]: usage.md#headings-levels +[SeHeadings]: usage.md#setext-style +[GFM Task]: https://github.github.com/gfm/#task-list-items-extension- diff --git a/docs/install.md b/docs/install.md new file mode 100644 index 00000000..a6892cfc --- /dev/null +++ b/docs/install.md @@ -0,0 +1,62 @@ +# Installation + +## Package Control + +It is highly recommended to install MarkdownEditing with [Package Control](https://packagecontrol.io) as it automatically installs required dependencies and keeps all packages up to date. + +1. [Install Package Control][InstallPackageControl] if you haven't yet. +2. Open Command Palette (Ctrl + Shift + P (Windows, Linux) or + + + P on Mac) +3. Type _Install Package_ and hit Enter to display a list of available packages. +4. Type _MarkdownEditing_ and hit Enter to install the package. + +### Pre-Releases + +If you are interested in testing bleeding edge features you can set up Package Control +to install pre-releases by adding MarkdownEditing to `install_prereleases` key +in the `Package Control.sublime-settings`. + +```JSON +"install_prereleases": +[ + "MarkdownEditing" +], +``` + +## Manual installation + +1. In Sublime Text, open the menu _Preferences > Browse Packages..._. + This is the Sublime Text Packages directory. +2. [Download and unzip][download] or [clone][] this repository to a directory _MarkdownEditing_ + in the Sublime Text Packages directory. +3. The folder structure should look like `[...]/Packages/MarkdownEditing/[files]`. + +### Cloning Repository + +##### Mac OS + +```shell +cd ~/Library/Application\ Support/Sublime\ Text/Packages/ +git clone https://github.com/SublimeText-Markdown/MarkdownEditing.git +``` + +##### Linux + +```shell +cd ~/.config/sublime-text/Packages +git clone https://github.com/SublimeText-Markdown/MarkdownEditing.git +``` + +##### Windows + +```shell +cd "%APPDATA%\Sublime Text\Packages" +git clone https://github.com/SublimeText-Markdown/MarkdownEditing.git +``` + +!!! note + Destination paths may differ depending on Sublime Text version. + +[InstallPackageControl]: https://packagecontrol.io/installation +[download]: https://github.com/SublimeText-Markdown/MarkdownEditing/archive/master.zip +[clone]: https://help.github.com/articles/cloning-a-repository diff --git a/lint_docs/RULES.md b/docs/linting.md similarity index 70% rename from lint_docs/RULES.md rename to docs/linting.md index 5d759526..26219172 100644 --- a/lint_docs/RULES.md +++ b/docs/linting.md @@ -1,4 +1,78 @@ -# Rules +# Lint feature for MarkdownEditing + +## Running Lint + +Open a markdown document and press ctrl() + shift() + M or input `MarkdownEditing: Markdown Lint` in Command Palette to try it. + +* **Markdown Lint** + Performs lint on current Markdown file using a local linter. See [lint rules](#rules). Some of the linting rules are customizable via user settings file. + +* **Run markdownlint** + Run mdl command from [markdownlint](https://github.com/markdownlint/markdownlint) package. You need to install it by yourself. + +## Editing Rules + +All rules are implemented in `lint.py`. In case you a rule is modified, please remember to also edit the description below. + +### How rules work + +All rules are implemented as separated subclasses of `mddef` class defined in `lint.py`. The lifespan of a rule instance is one lint process. There are several important fields in every rule class: + +| Name | Type | Comment | +|------|------|---------| +| flag | int | the flag used to search for locator (default: 0) | +| desc | str | description of the rule | +| locator | str | a regex that will be used to locate the targets | +| gid | int | the id of the group in locator that will be passed to test method (default: 0) | +| finish | bool | the linter will stop scanning the rest of the document if it is true (default: false) | + +and a "test" method like this: + +```python +def test(self, text, s, e): + if isIllegal(text[s:e]): + return {the_offset: "additional information"} + else: + return {} +``` + +The linter will search for all occurrences of `locator` with regexp flag equals to `flag` in the document. Then it passes the document itself and the begin position and the end position of target captured group to `test` method. The `test` method will return a dictionary of "offset:information" key-value pairs. That offset will decide the displayed line number of the occurrence of the error. + +### Editing an existing rule + +First you need to know the name of that rule (e.g. MD001), and search for the class with the same name in `lint.py` (e.g. `md001`). You may want to change the `locator` to narrow down (or expand) the applied domain first before editing `test` method. + +### Creating new rules + +Every rule is a subclass of `mdddef`. Here is an example: + +```python +class md001(mddef): + flag = re.M # re.M is for multiline mode + desc = 'Header levels should only increment by one level at a time' + locator = r'^#{1,6}(?!#)' # This is for atx and atx_closed style headers + + lastMatch = None # We are comparing two successive headers, so we + # need to store the previous one + + def test(self, text, s, e): + ret = {} + if self.lastMatch: + n1 = len(self.lastMatch) # the length of the captured group + n2 = e - s # is the level of the header + if n2 > n1 and n2 != n1 + 1: + ret[s] = 'expected %d, %d found' % (n1 + 1, n2) + self.lastMatch = text[s: e] + return ret +``` + +You can create new settings as well. Just follow the examples of existing rules and the value of settings are stored as `self.settings`. + +## Discussion + +You can share your opinions through [issues](https://github.com/SublimeText-Markdown/MarkdownEditing/issues). + +## Rules This document contains a description of all rules, what they are checking for, as well as an examples of documents that break the rule and corrected @@ -6,7 +80,7 @@ versions of the examples. The rules are mostly [from markdownlint](https://github.com/mivok/markdownlint/blob/master/docs/RULES.md). -## MD001 - Header levels should only increment by one level at a time +### MD001 - Header levels should only increment by one level at a time This rule is triggered when you skip header levels in a markdown document, for example: @@ -34,7 +108,7 @@ level at a time: This rule only applies to atx and atx_closed styles of headers. -## MD002 - First header should be a h1 header +### MD002 - First header should be a h1 header This rule is triggered when the first header in the document isn't a h1 header: @@ -50,7 +124,7 @@ The first header in the document should be a h1 header: This rule applies to all three styles of headers. -## MD003 - Header style +### MD003 - Header style This rule is triggered when different header styles (atx, setext, and 'closed' atx) are used in the same document: @@ -72,7 +146,7 @@ Note: the configured header style can be a specific style to use (atx, atx_closed, setext), or simply require that the usage be consistent within the document. -## MD004 - Unordered list style +### MD004 - Unordered list style This rule is triggered when the symbols used in the document for unordered list items do not match the configured unordered list style: @@ -92,7 +166,7 @@ Note: the configured list style can be a specific symbol to use (asterisk, plus, dash), or simply require that the usage be consistent within the document, or require that the three different symbols to be used cyclically on different level or same symbol on same levels. -## MD005 - Inconsistent indentation for list items at the same level +### MD005 - Inconsistent indentation for list items at the same level This rule is triggered when list items are parsed as being at the same level, but don't have the same indentation: @@ -110,7 +184,7 @@ for the list to fix it: * Nested Item 2 * Nested Item 3 -## MD006 - Consider starting bulleted lists at the beginning of the line +### MD006 - Consider starting bulleted lists at the beginning of the line This rule is triggered when top level lists don't start at the beginning of a line: @@ -134,7 +208,7 @@ or the tab key is used to indent. Starting a list 1 space in means that the indent of the first nested list is less than the indent of the second level (3 characters if you use 4 space tabs, or 1 character if you use 2 space tabs). -## MD007 - Unordered list indentation +### MD007 - Unordered list indentation This rule is triggered when list items are not indented by the configured number of spaces (default: current Sublime tab_size). @@ -163,14 +237,14 @@ require a 4 space indents. See for a description of the problem. -## MD009 - Trailing spaces +### MD009 - Trailing spaces This rule is triggered on any lines that end with whitespace. To fix this, find the line that is triggered and remove any trailing spaces from the end. Note: this rule can be triggered inside code/quote block. -## MD010 - Hard tabs +### MD010 - Hard tabs This rule is triggered on any lines that contain hard tab characters instead of using spaces for indentation. To fix this, replace any hard tab characters @@ -188,7 +262,7 @@ Corrected example: * Spaces used to indent the list item instead -## MD011 - Reversed link syntax +### MD011 - Reversed link syntax This rule is triggered when text that appears to be a link is encountered, but where the syntax appears to have been reversed (the `[]` and `()` are @@ -200,7 +274,7 @@ To fix this, swap the `[]` and `()` around: [Correct link syntax](http://www.example.com/) -## MD012 - Multiple consecutive blank lines +### MD012 - Multiple consecutive blank lines Tags: whitespace, blank_lines @@ -221,7 +295,7 @@ To fix this, delete the offending lines: Note: this rule will not be triggered if there are multiple consecutive blank lines inside code blocks. -## MD013 - Line length +### MD013 - Line length This rule is triggered when there are lines that are longer than the configured line length (default: current Sublime wrap_width). To fix this, split the line @@ -229,7 +303,7 @@ up into multiple lines. This rule is disabled by default. -## MD018 - No space after hash on atx style header +### MD018 - No space after hash on atx style header This rule is triggered when when spaces are missing after the hash characters in an atx style header: @@ -245,7 +319,7 @@ space: ## Header 2 -## MD019 - Multiple spaces after hash on atx style header +### MD019 - Multiple spaces after hash on atx style header This rule is triggered when when more than one space is used to separate the header text from the hash characters in an atx style header: @@ -261,7 +335,7 @@ space: ## Header 2 -## MD020 - No space inside hashes on closed atx style header +### MD020 - No space inside hashes on closed atx style header This rule is triggered when when spaces are missing inside the hash characters in a closed atx style header: @@ -279,7 +353,7 @@ space: Note: this rule will fire if either side of the header is missing spaces. -## MD021 - Multiple spaces inside hashes on closed atx style header +### MD021 - Multiple spaces inside hashes on closed atx style header This rule is triggered when when more than one space is used to separate the header text from the hash characters in a closed atx style header: @@ -298,7 +372,7 @@ space: Note: this rule will fire if either side of the header contains multiple spaces. -## MD022 - Headers should be surrounded by blank lines +### MD022 - Headers should be surrounded by blank lines This rule is triggered when headers (any style) are either not preceded or not followed by a blank line: @@ -320,11 +394,11 @@ To fix this, ensure that all headers have a blank line both before and after ## Header 2 -Rationale: Aside from asthetic reasons, some parsers, including kramdown, will +Rationale: Aside from aesthetic reasons, some parsers, including kramdown, will not parse headers that don't have a blank line before, and will parse them as regular text. -## MD023 - Headers must start at the beginning of the line +### MD023 - Headers must start at the beginning of the line This rule is triggered when a header is indented by one or more spaces: @@ -341,7 +415,7 @@ To fix this, ensure that all headers start at the beginning of the line: Rationale: Headers that don't start at the beginning of the line will not be parsed as headers, and will instead appear as regular text. -## MD024 - Multiple headers with the same content +### MD024 - Multiple headers with the same content This rule is triggered if there are multiple headers in the document that have the same text: @@ -360,7 +434,7 @@ Rationale: Some markdown parses generate anchors for headers based on the header name, and having headers with the same content can cause problems with this. -## MD025 - Multiple top level headers in the same document +### MD025 - Multiple top level headers in the same document This rule is triggered when a top level header is in use (the first line of the file is a h1 header), and more than one h1 header is in use in the @@ -385,7 +459,7 @@ serves as the title for the document. If this convention is in use, then there can not be more than one title for the document, and the entire document should be contained within this header. -## MD026 - Trailing punctuation in header +### MD026 - Trailing punctuation in header This rule is triggered on any header that has a punctuation character as the last character in the line: @@ -400,7 +474,7 @@ Note: The punctuation parameter can be used to specify what characters class as punctuation at the end of the header (defaults to `".,;:!"`). For example, you can set it to `".,;:"` to allow headers with exclamation marks in them. -## MD027 - Multiple spaces after blockquote symbol +### MD027 - Multiple spaces after blockquote symbol This rule is triggered when blockquotes have more than one space after the blockquote (`>`) symbol: @@ -413,7 +487,7 @@ To fix, remove any extraneous space: > This is a blockquote with correct > indentation. -## MD028 - Blank line inside blockquote +### MD028 - Blank line inside blockquote This rule is triggered when two blockquote blocks are separated by nothing except for a blank line: @@ -444,7 +518,7 @@ Rationale: Some markdown parsers will treat two blockquotes separated by one or more blank lines as the same blockquote, while others will treat them as separate blockquotes. -## MD029 - Ordered list item prefix +### MD029 - Ordered list item prefix This rule is triggered on ordered lists that do not either start with '1.' or do not have a prefix that increases in numerical order (depending on the diff --git a/docs/requirements.txt b/docs/requirements.txt new file mode 100644 index 00000000..b873ebf9 --- /dev/null +++ b/docs/requirements.txt @@ -0,0 +1,6 @@ +mkdocs +mkdocs-cinder +mkdocs-git-revision-date-localized-plugin +mkdocs-mermaid-plugin +mkdocs-minify-plugin +pymdown-extensions diff --git a/docs/troubleshooting.md b/docs/troubleshooting.md new file mode 100644 index 00000000..bfab73fe --- /dev/null +++ b/docs/troubleshooting.md @@ -0,0 +1,127 @@ +# Troubleshooting + +## 3.0.0 Migration Guide + +### Preferences need manual update + +MarkdownEditing stores settings in _Preferences.sublime-settings_ as of version 3.0.0. + +Thus all user specific syntax specific settings or overrides can or must be removed: + +1. Open a Markdown file +2. Open Command Palette ctrl+shift+p +3. Execute `Preferences: Settings - Syntax Specific` +4. Remove everything judjged useless from the right panel. + +The following syntax specific settings have been removed: + +```json +{ + "color_scheme": "Packages/MarkdownEditing/MarkdownEditor.tmTheme", + + "tab_size": 4, + "translate_tabs_to_spaces": true, + "trim_trailing_white_space_on_save": false, + "auto_match_enabled": true, + + // Layout + "draw_centered": true, + "word_wrap": true, + "wrap_width": 80, + "rulers": [], + + // Line + "line_numbers": false, + "highlight_line": false, + "line_padding_top": 2, + "line_padding_bottom": 2, + + // Caret + "caret_style": "wide", + "caret_extra_top": 3, + "caret_extra_bottom": 3, +} +``` + +### Custom key bindings need manual update + +Macro calls and key binding contexts have been changed heavily. + +Commands have been renamed in order to avoid possible conflicts with other packages. +Others have been split to follow naming scheme of ST's built-in commands +(e.g. indent/unindent commands). + +Hints about required or optional arguments may be found in +_MarkdownEditing/Default (...).sublime-keymap_. + +| old names | new names +|------------------------------------|-------------------------------------- +| - | mde_change_headings_level +| - | mde_fold_links +| - | mde_match_heading_hashes +| - | mde_toggle_centered_line +| - | mde_toggle_task_list_item +| - | mde_unindent_list_item +| complete_underlined_header | mde_complete_underlined_headings +| convert_inline_link_to_reference | mde_convert_inline_link_to_reference +| convert_inline_links_to_references | mde_convert_inline_links_to_references +| convert_to_atx | mde_convert_underlined_headings_to_atx +| deindent_quote | mde_unindent_quote +| fix_all_underlined_headers | mde_fix_underlined_headings +| fold_all_sections | mde_fold_all_sections +| fold_section | mde_fold_section +| gather_missing_footnotes | mde_gather_missing_footnotes +| gather_missing_link_markers | mde_gather_missing_link_markers +| goto_next_heading | mde_goto_next_heading +| goto_previous_heading | mde_goto_previous_heading +| indent_list_item | mde_indent_list_item +| indent_list_multiitem | _(use mde_indent_list_item instead)_ +| indent_quote | mde_indent_quote +| list_back_links | mde_list_back_links +| magic_footnotes | mde_magic_footnotes +| make_page_reference | mde_make_page_reference +| markdown_lint | mde_markdown_lint +| markdown_lint_mdl | mde_markdown_lint_mdl +| mde_color_activate | mde_select_color_scheme +| number_list | mde_number_list +| number_list_reference | mde_add_numbered_reference_definition +| open_home_page | mde_open_home_page +| open_journal | mde_open_journal +| open_page | mde_open_page +| reference_delete_reference | mde_reference_delete_reference +| reference_jump | mde_reference_jump +| reference_new_footnote | mde_reference_new_footnote +| reference_new_image | mde_reference_new_image +| reference_new_inline_image | mde_reference_new_inline_image +| reference_new_inline_link | mde_reference_new_inline_link +| reference_new_reference | mde_reference_new_reference +| reference_organize | mde_reference_organize +| show_fold_all_sections | mde_show_fold_all_sections +| switch_list_bullet_type | mde_switch_list_bullet_type +| unfold_all_sections | mde_unfold_all_sections + +## Error loading syntax file + +!!! warning + Error loading syntax file "Packages/Markdown/Markdown.sublime-syntax": Unable to open Packages/Markdown/Markdown.sublime-syntax + +MarkdownEditing does its best to reassign syntax of open files after installation or during upgrade. + +However open markdown files at install time may cause this issue. You have to **manually change their syntax to your newly installed Markdown syntax** then. + +!!! info _Note_ + The default _Markdown_ package shipped with Sublime Text is disabled automatically as it causes some conflicts. You may need to enable it manually after disabling or uninstalling MarkdownEditing. + +## Roll back to an older version + +When you notice any undesired behaviour introduced by the latest update, your feedback is always welcome at [issue page][mdeissues]. However before it's fixed, you can rollback to [an earlier version][mdereleases]. Find the desired version and download the zip file, then follow [manual installation guide](#manual-installation) + +## Known Bugs + +* Setext-style headers (`===` and `---`) do not show up in the symbol list. This is due to a Sublime Text limitation (see [#158][]). However, we are able to put a placeholder to indicate the existence of the header. We encourage you to use Atx-style headers (`#`). + +* Installing for the first time while having markdown files opened may cause MarkdownEditing to behave unexpectedly on those files. Close and reopen those files to fix it. + +[#158]: https://github.com/SublimeText-Markdown/MarkdownEditing/issues/158 +[mdereleases]: https://github.com/SublimeText-Markdown/MarkdownEditing/releases +[mdeissues]: https://github.com/SublimeText-Markdown/MarkdownEditing/issues diff --git a/docs/usage.md b/docs/usage.md new file mode 100644 index 00000000..0cdcdf28 --- /dev/null +++ b/docs/usage.md @@ -0,0 +1,308 @@ +# Text Formatting + +MarkdownEditing supports formatting text by + +* auto-pairing corresponding markup characters +* special purpose key bindings + +## Auto Pairing + +MarkdownEditing extends extends ST's auto pairing capabilities. + +* Asterisks (\*), backticks (\`) and underscores (\_) are auto-paired and wrap selected text +* ~ wraps selected text with `~~` (strike-through) +* Backspace deletes an empty pair +* Space or Tab deletes right element of empty pair of asterisks or underscores + +This feature is controlled by global `auto_match_enabled` setting. + +## Key Bindings + +These are bound to bold and italic. They work both with and without selections. If there is no selection, they will just transform the word under the cursor. These key bindings will unbold/unitalicize selection if it is already bold/italic. + +| markup | rendered | Linux/Windows | MacOS +|--------------|------------|-------------------------------|--------------------------------------------- +\*\*bold\*\* | **bold** | Alt + B | + + B +\_italic\_ | _italic_ | Alt + I | + + I +\~\~strike\~\~ | ~~strike~~ | | +\`code\` | `code` | | + +# Headings + +## Headings Styles + +### ATX style + +MarkdownEditing assists with maintaining desired ATX headings style by keeping closing hashes balanced or by removing them automatically. + +_This feature can be disabled by setting `"mde.auto_match_heading_hashes": false`._ + +You can switch between open and closed heading style for the active view via Command Palette: + +* **MarkdownEditing: Add Closing Heading Hashes** + Sets: `"mde.match_heading_hashes": true` and adds closing hashes to all headings. + +* **MarkdownEditing: Remove Closing Heading Hashes** + Sets: `"mde.match_heading_hashes": false` and removes closing hashes to all headings. + +* **MarkdownEditing: Fix Closing Heading Hashes** + Adds or removes closing hashes according to value of `"mde.match_heading_hashes"` without modifying it. + +By default heading style is detected when loading or saving a file and stored in view specific settings. + +A value of `"mde.match_heading_hashes": false` means _"open style"_: + +```markdown +## ATX heading + +Open style without closing hashes. +``` + +A value of `"mde.match_heading_hashes": true` means _"closed style"_: + +```markdown + +## ATX heading ## + +Closed style with closing hashes. +``` + +_Auto-detection can be disabled by `"mde.detect_heading_style": false`._ + +In that case you can manually enforce a style via `"mde.match_heading_hashes"` in user preferences or project specific settings. + +### Setext style + +MarkdownEditing assists with maintaining width of underlined headings during typing. + +Just hit tab after `-` or `=` and underline width is adjusted to headings text length. + +![headings-setext](img/headings-setext.png) + +All headings can be fixed or converted at once via Command Palette: + +* **MarkdownEditing: Fix Underlined Headings** + Adjusts every setext-style header to add or remove `=` or `-` characters as needed to match the lengths of their header text. + +* **MarkdownEditing: Convert Underlined Headings to ATX** + Converts every setext-style header into an ATX style header. If something is selected only the headers in the selections will be converted, otherwise the conversion will be applied to the whole view. + +## Headings Levels + +Headings levels can be modified by placing caret to desired lines and run a command via Command Palette: + +* **MarkdownEditing: Convert Heading to Text** + Removes all hashes. + +* **MarkdownEditing: Set Headings Level x** + Replaces any number of existing hashes by `x` hashes. + +* **MarkdownEditing: Increase Headings Level** + Add one additional hash. + +* **MarkdownEditing: Decrease Headings Level** + Remove one hash. + +or use one of the following bindings: + +| Linux/Windows | MacOS | Description +|---------------|-------|------------- +| ctrl + alt + 0 | + ^ + 0 | convert headings into normal text +| ctrl + alt + 1..6 | + ^ + 1..6 | set headings level to 1..6 +| ctrl + alt + , | + ^ + , | reduce headings level by one +| ctrl + alt + . | + ^ + . | increase headings level by one + +Adding or removing `#` at the beginning of lines also modifies heading levels implicitly while maintaining open or closed heading styles. + +### Constraints + +1. Unordered lists are not converted to headings. + + ``` + * item + * [ ] task + ``` + +2. All functions work with multiple selections. +3. If a selection spans multiple lines a heading is created for each line + separately. + +## Folding Sections + +Irrelevant sections of documents can be folded/collapsed via Command Palette: + +* **MarkdownEditing: Toggle Folding Current Section** + Whether child sections are folded or unfolded as well depends on folding level defined by calling one of the following commands. + + If `Fold All Sections` was called before _("outline mode" is active)_, the region between current and following sibling or child heading is (un)folded only. + + If `Fold Level 1-6 Sections` was called before, all child sections with lower level keep folded when unfolding their parent section. + + If `Unfold All Sections` was called before, all child sections are (un)folded. + +* **MarkdownEditing: Fold Level 1-6 Sections** + Folds all sections of headings of specific level. Also hides lower level headings. + +* **MarkdownEditing: Fold All Sections** + Folds all sections of any level but keeps their headings visible. Let's call it "outline mode". + +* **MarkdownEditing: Unfold All Sections** + Self explanatory. + +Folding is bound to following keys by default: + +| Linux/Windows | MacOS | Description +|---------------|-------|------------- +| ctrl + k, ctrl + 0 | + k, + 0 | Unfold all sections +| ctrl + k, ctrl + 1..6 | + k, + 1..6 | Fold sections by level 1..6 +| ctrl + k, ctrl + 9 | + k, + 9 | Fold all sections, but keep headings of any level visible +| Shift + Tab | + Tab | Fold/Unfold current section. +| Ctrl + Shift + Tab | ^ + + Tab | Fold all sections under headings of a certain level. + +## Navigation + +MarkdownEditing provides various ways to navigate between sections. + +Headings are listed via + +* Goto Symbol (Ctrl + R) +* Goto Symbol in Project (Ctrl + Shift + R) + +Relevant commands are exposed via Command Palette: + +* **MarkdownEditing: Goto Previous/Next Heading (Any Level)** + Jump to very previous or next heading + +* **MarkdownEditing: Goto Previous/Next Heading (Same or higher Level)** + Jump to previous or next heading of same or higher level + +Navigation is bound to following keys by default: + +| Linux/Windows | MacOS | Description +|---------------|-------|------------- +| Ctrl + Shift + PageUp/PageDown | + + PageUp/PageDown | Go to the previous/next heading of any level +| Ctrl + Alt + Shift + PageUp/PageDown | + + PageUp/PageDown | Go to the previous/next heading of the same or higher level + +# Lists and Tasks + +List bullets are automatically changed when indenting or unindenting list items by default. This behaviour can be disabled via `"mde.list_indent_auto_switch_bullet": false`. + +Markdown can support with keeping list item text aligned at tab width if `"mde.list_align_text": true` is set. + +Following commands are provided via Command Palette: + +* **Switch List Bullet Type** + Switches the highlighted list between numbered and bulleted style. + +Following key bindings may be used to create or toggle tasks. + +| Linux/Windows | MacOS | Description +|---------------|-------|------------- +| Alt + t | + + t | Creates new GFM task (`* [ ] task`) +| Alt + x | + + x | Toggles GFM task check marks (`* [X] task`) + +# References + +Following commands are provided via Command Palette: + +* **Add Missing Link Labels** + Scans document for referenced link usages (`[some link][some_ref]` and `[some link][]`) and checks if they are all defined. If there are undefined link references, command will automatically create their definition snippet at the bottom of the file. + +* **Magic Footnotes Command** + Adds a footnote after the word under cursor. If cursor is already on a footnote, jumps to its definition or reference. + +* **Gather Missing Footnotes** + Add definition stubs (if there is none) for all footnotes references. + +* **Jump Reference** + Jumps cursor between definitions and references. + +* **New Reference** + Adds a new link under cursor. + +* **New Inline Link** + Adds a new inline link under cursor. + +* **New Inline Image** + Adds a new inline image under cursor. + +* **New Image** + Adds a new image under cursor. + +* **New Footnote** + Adds a footnote under cursor. + +* **Delete Reference** + Deletes the definition and references of a link. + +* **Organize References** + Sorts and gives a report on current link references usage. + + +Important functions are bound to following keys by default: + +| Linux/Windows | MacOS | Description +|---------------|-------|------------- +| Ctrl + Alt + V | + + V | Creates or pastes the contents of the clipboard as an inline link on selected text. +| Ctrl + Alt + R | + + R | Creates or pastes the contents of the clipboard as a reference link. +| Shift + Win + K | + + K | Creates or pastes the contents of the clipboard as an inline image on selected text. +| Alt + Shift + 6 | + + 6 | Inserts a footnote. + +# Critic Markup + +MarkdownEditing supports document review by highlighting critic markup and enable adding critic or accepting and rejecting proposed changes via key bindings. + +## Reviewer + +A document reviewer can insert critic or propose changes for single words or selections with following key bindings: + +| Linux/Windows | MacOS | Description +|---------------|-------|------------- +| Alt + c, Alt + a | + + c, + + a | Insert or convert selection into `{++ addition ++}`. +| Alt + c, Alt + c | + + c, + + c | Insert or convert selection into `{>> comment <<}`. +| Alt + c, Alt + d | + + c, + + d | Convert word or selection into `{-- deletion --}`. +| Alt + c, Alt + h | + + c, + + h | Convert word or selection into `{== highlight==}{>> comment <<}`. +| Alt + c, Alt + s | + + c, + + s | Convert word or selection into `{~~ substitution ~> by ~~}`. + +## Author + +A document author can accept or reject suggestions with following key bindings once caret was moved into critic markup: + +| Linux/Windows | MacOS | Description +|---------------|-------|------------- +| Alt + Enter | + + Enter | Accept critic and apply proposed change. +| Alt + Backspace | + + Backspace | Reject critic and discard proposed changes. + +!!!note "Note" + `{>> comment <<}` and `{== highlight==}` are removed by both bindings. + +# Wiki + +Wiki links are defined by surrounding a (wiki) word with double square brackets, for example: + + [[SampleWikiPage]] + +The user can `open` wiki page using a sublime command. This will search the current open file's directory (and sub-directories) for a file with a matching name and a markdown extension. For example, opening the previous wiki link +will look for and open a file named: + + SampleWikiPage.md + +Note that, if the wiki page does *not* yet exist, if will be created with a header matching the page name. However the file will only actually be created on the file system, when it is saved by the user. + +The user can `list back links` and of course to open them. Back links are pages that reference the current page. This allows pages to be tied together into a personal wiki. A common technique is to define *tag* wiki pages and to list any tags for a page as references to the tag pages at the bottom of the page, for example: + + [[TagSyntax]] [[TagDev]] [[TagPython]] + +This allows the user to list all pages with a specific tag, by opening the tag page and list all back links. + +Journal wiki pages are also supported. A journal page is just a wiki page with a name matching the current date. + +Lastly the command to open the *home* page is provided, where the home page is just a wiki page named `HomePage`. + + +| Linux/Windows | MacOS | Description +|---------------|-------|------------- +| Ctrl + Shift + H | + + H | Open home page +| Ctrl + Shift + D | + + D | Open wiki page under the cursor +| Ctrl + Shift + J | + + J | Open journal page for today +| Ctrl + Shift + B | + + B | List back links diff --git a/folding.py b/folding.py deleted file mode 100644 index 109cf4e0..00000000 --- a/folding.py +++ /dev/null @@ -1,247 +0,0 @@ -import sublime -import sublime_plugin -import re -try: - from MarkdownEditing.mdeutils import * -except ImportError: - from mdeutils import * - - -def getFoldedRegion(view, reg): - for i in view.folded_regions(): - if i.contains(reg): - return i - return None - - -def all_headings(view): - text = view.substr(sublime.Region(0, view.size())) - it = re.finditer(r'^(#{1,6}(?!#))|^(-{3,}|={3,})', text, re.M) - for m in it: - if '.front-matter' in view.scope_name(m.start()): - continue - if re.match(r'^(-{3,}|={3,})$', m.group()): - title_end = m.start() - 1 - title_begin = text.rfind('\n', 0, title_end) + 1 - title_end = m.end() - level = 2 if text[m.start()] == '-' else 1 - else: - title_begin = m.end() - title_end = re.search('(' + m.group() + ')?(\n|$)', text[title_begin:]).start() + title_begin - title_begin = m.start() - level = m.end() - m.start() - if 'markup.raw.block.markdown' not in view.scope_name(title_begin).split(' '): - yield (title_begin, title_end, level) - - -def get_current_level(view, p): - last_level = 0 - for (title_begin, title_end, level) in all_headings(view): - if title_end < p: - last_level = level - elif title_begin < p: - return level - else: - return last_level - - -class FoldSectionCommand(MDETextCommand): - - def description(self): - return 'Toggle fold/unfold on current section' - - def run(self, edit): - view = self.view - sections = [] - shouldUnfold = False - for sel in view.sel(): - section_start = -1 - section_end = view.size() - section_level = 0 - for (title_begin, title_end, level) in all_headings(view): - if title_begin <= sel.a: - section_start = title_end - section_level = level - elif section_level >= level: - section_end = title_begin - 1 - break - if section_start >= 0 and section_end >= section_start: - reg = sublime.Region(section_start, section_end) - folded = getFoldedRegion(view, reg) - if folded != None: - sections.append(folded) - shouldUnfold = True - else: - sections.append(reg) - - for reg in sections: - if shouldUnfold: - view.unfold(reg) - else: - view.fold(reg) - sublime.status_message('%d region%s %sfolded' % (len(sections), 's' if len(sections) > 1 else '', 'un' if shouldUnfold else '')) - - -class FoldSectionContextCommand(FoldSectionCommand): - - def is_visible(self): - if not FoldSectionCommand.is_visible(self): - return False - view = self.view - hasSection = False - for sel in view.sel(): - section_start = -1 - section_end = view.size() - section_level = 0 - for (title_begin, title_end, level) in all_headings(view): - if title_begin <= sel.a: - section_start = title_end - section_level = level - elif section_level >= level: - section_end = title_begin - 1 - break - if section_start >= 0 and section_end >= section_start: - reg = sublime.Region(section_start, section_end) - folded = getFoldedRegion(view, reg) - if folded != None: - return False - else: - hasSection = True - return hasSection - - -class UnfoldSectionContextCommand(FoldSectionCommand): - - def is_visible(self): - if not FoldSectionCommand.is_visible(self): - return False - view = self.view - hasSection = False - for sel in view.sel(): - section_start = -1 - section_end = view.size() - section_level = 0 - for (title_begin, title_end, level) in all_headings(view): - if title_begin <= sel.a: - section_start = title_end - section_level = level - elif section_level >= level: - section_end = title_begin - 1 - break - if section_start >= 0 and section_end >= section_start: - reg = sublime.Region(section_start, section_end) - folded = getFoldedRegion(view, reg) - if folded != None: - hasSection = True - else: - return False - return hasSection - - -class ShowFoldAllSectionsCommand(MDETextCommand): - - def run(self, edit): - view = self.view - view.window().run_command('show_overlay', {'overlay': 'command_palette', 'text': 'MarkdownEditing: Fold'}) - - -class FoldAllSectionsCommand(MDETextCommand): - - def run(self, edit, target_level=0): - view = self.view - view.run_command('unfold_all') - section_start = -1 - section_end = view.size() - n_sections = 0 - for (title_begin, title_end, level) in all_headings(view): - if target_level == 0 or level <= target_level: - if section_start > 0: - section_end = title_begin - 1 - reg = sublime.Region(section_start, section_end) - view.fold(reg) - n_sections += 1 - section_start = -1 - if target_level == 0 or level == target_level: - section_start = title_end - if section_start >= 0: - reg = sublime.Region(section_start, view.size()) - view.fold(reg) - n_sections += 1 - if len(view.sel()) > 0: - for sel in view.sel(): - if getFoldedRegion(view, sel) == None: - view.show(sel) - else: - view.show(sublime.Region(0, 0)) - sublime.status_message('%d region%s folded' % (n_sections, 's' if n_sections > 1 else '')) - - -class UnfoldAllSectionsCommand(MDETextCommand): - - def run(self, edit): - view = self.view - view.run_command('unfold_all') - - -class GotoNextHeadingCommand(MDETextCommand): - - def run(self, edit, same_level=True): - view = self.view - new_sel = [] - for sel in view.sel(): - section_level = 0 - found = False - for (title_begin, title_end, level) in all_headings(view): - if title_begin <= sel.a: - section_level = level - elif not same_level or section_level >= level: - found = True - break - if found: - new_sel.append(sublime.Region(title_begin, title_end)) - if len(new_sel) == 0: - sublime.status_message('No heading can be found') - else: - view.sel().clear() - for region in new_sel: - view.sel().add(region) - view.show(region) - - -class GotoPreviousHeadingCommand(MDETextCommand): - - def run(self, edit, same_level=True): - view = self.view - new_sel = [] - max_level = 0 - last_level = 0 - found = False - for sel in view.sel(): - prev = {} - for (title_begin, title_end, level) in all_headings(view): - max_level = max(max_level, level) - if title_end < sel.a: - for lvl in range(level, max_level + 1): - prev[lvl] = (title_begin, title_end) - last_level = level - else: - found = True - break - if found: - if same_level: - while level not in prev and level > 0: - level -= 1 - if level > 0 and level in prev: - new_sel.append(sublime.Region(prev[level][0], prev[level][1])) - else: - if last_level > 0 and last_level in prev: - new_sel.append(sublime.Region(prev[last_level][0], prev[last_level][1])) - elif max_level > 0: - new_sel.append(sublime.Region(title_begin, title_end)) - if len(new_sel) == 0: - sublime.status_message('No heading can be found') - else: - view.sel().clear() - for region in new_sel: - view.sel().add(region) - view.show(region) diff --git a/indent_list_item.py b/indent_list_item.py deleted file mode 100644 index 6b7d49aa..00000000 --- a/indent_list_item.py +++ /dev/null @@ -1,49 +0,0 @@ -import sublime_plugin -import re -try: - from MarkdownEditing.mdeutils import * -except ImportError: - from mdeutils import * - - -class IndentListItemCommand(MDETextCommand): - - def run(self, edit, reverse=False): - for region in self.view.sel(): - line = self.view.line(region) - line_content = self.view.substr(line) - - bullets = self.view.settings().get("mde.list_indent_bullets", ["*", "-", "+"]) - bullet_pattern = '([' + ''.join(re.escape(i) for i in bullets) + '])' - - new_line = line_content - - # Transform the bullet to the next/previous bullet type - if self.view.settings().get("mde.list_indent_auto_switch_bullet", True): - - for key, bullet in enumerate(bullets): - if bullet in new_line: - if reverse and new_line.startswith(bullet) and key is 0: - # In this case, do not switch bullets - continue - - new_line = new_line.replace(bullet, bullets[(key + (1 if not reverse else -1)) % len(bullets)]) - break - - # Determine how to indent (tab or spaces) - if self.view.settings().get("translate_tabs_to_spaces"): - tab_str = self.view.settings().get("tab_size", 4) * " " - - else: - tab_str = "\t" - - if not reverse: - # Do the indentation - new_line = re.sub(bullet_pattern, tab_str + "\\1", new_line) - - else: - # Do the unindentation - new_line = re.sub(tab_str + bullet_pattern, "\\1", new_line) - - # Insert the new item - self.view.replace(edit, line, new_line) diff --git a/indent_list_multiitem.py b/indent_list_multiitem.py deleted file mode 100644 index 7ac07a6a..00000000 --- a/indent_list_multiitem.py +++ /dev/null @@ -1,66 +0,0 @@ -import sublime_plugin -import re -try: - from MarkdownEditing.mdeutils import * -except ImportError: - from mdeutils import * - - -class IndentListMultiitemCommand(MDETextCommand): - - def run(self, edit, reverse=False): - todo = [] - for region in self.view.sel(): - lines = self.view.line(region) - lines = self.view.split_by_newlines(lines) - for line in lines: - line_content = self.view.substr(line) - - if len(line_content) == 0: - continue - - # Determine how to indent (tab or spaces) - if self.view.settings().get("translate_tabs_to_spaces"): - tab_str = self.view.settings().get("tab_size", 4) * " " - - else: - tab_str = "\t" - - if re.match("^\\s*(>\\s*)?[*+\\-]\\s+(.*)$", line_content): - bullets = self.view.settings().get("mde.list_indent_bullets", ["*", "-", "+"]) - bullet_pattern = '([' + ''.join(re.escape(i) for i in bullets) + '])' - bullet_pattern_a = "^\\s*(?:>\\s*)?(" - bullet_pattern_b = ")\\s+" - new_line = line_content - # Transform the bullet to the next/previous bullet type - if self.view.settings().get("mde.list_indent_auto_switch_bullet", True): - for key, bullet in enumerate(bullets): - re_bullet = re.escape(bullet) - search_pattern = bullet_pattern_a + \ - re_bullet + bullet_pattern_b - if re.search(search_pattern, line_content): - if reverse and new_line.startswith(bullet) and key is 0: - # In this case, do not switch bullets - continue - new_bullet = bullets[(key + (1 if not reverse else -1)) % len(bullets)] - new_line = re.sub(re_bullet, new_bullet, new_line, 1) - break - if not reverse: - # Do the indentation - new_line = re.sub(bullet_pattern, tab_str + "\\1", new_line, 1) - - else: - # Do the unindentation - new_line = re.sub(tab_str + bullet_pattern, "\\1", new_line, 1) - else: - if not reverse: - new_line = tab_str + line_content - else: - new_line = re.sub(tab_str, "", line_content, 1) - - # Insert the new item - todo.append([line, new_line]) - - while len(todo) > 0: - j = todo.pop() - self.view.replace(edit, j[0], j[1]) diff --git a/lint_docs/README.md b/lint_docs/README.md deleted file mode 100644 index 4bc888b4..00000000 --- a/lint_docs/README.md +++ /dev/null @@ -1,67 +0,0 @@ -# Lint feature for MarkdownEditing - -This feature is still experimental. Use at your own risk. - -Open a markdown document and press `ctrl()+shift()+M` or input `MarkdownEditing: Markdown Lint` in command pallette to try it. - -## Editing rules - -All rules are described in `lint_docs/RULES.md`, and implemented in `lint.py`. When you edit a rule, remember to edit the description in `RULES.md`. - -### How rules work - -All rules are implemented as seperated subclasses of `mddef` class defined in `lint.py`. The lifespan of a rule instance is one lint process. There are several important fields in every rule class: - -| Name | Type | Comment | -|------|------|---------| -| flag | int | the flag used to search for locator (default: 0) | -| desc | str | description of the rule | -| locator | str | a regex that will be used to locate the targets | -| gid | int | the id of the group in locator that will be passed to test method (default: 0) | -| finish | bool | the linter will stop scanning the rest of the document if it is true (default: false) | - -and a "test" method like this: - -```python -def test(self, text, s, e): - if isIllegal(text[s:e]): - return {the_offset: "additional information"} - else: - return {} -``` - -The linter will search for all occcurences of `locator` with regex flag equals to `flag` in the document. Then it passes the document itself and the begin position and the end position of target captured group to `test` method. The `test` method will return a dictionary of "offset:information" key-value pairs. That offset will decide the displayed line number of the occurence of the error. - -### Editing an existing rule - -First you need to know the name of that rule (e.g. MD001), and search for the class with the same name in `lint.py` (e.g. `md001`). You may want to change the `locator` to narrow down (or expand) the applied domain first before editing `test` method. - -### Creating new rules - -Every rule is a subclass of `mdddef`. Here is an example: - -```python -class md001(mddef): - flag = re.M # re.M is for multiline mode - desc = 'Header levels should only increment by one level at a time' - locator = r'^#{1,6}(?!#)' # This is for atx and atx_closed style headers - - lastMatch = None # We are comparing two successive headers, so we - # need to store the previous one - - def test(self, text, s, e): - ret = {} - if self.lastMatch: - n1 = len(self.lastMatch) # the length of the captured group - n2 = e - s # is the level of the header - if n2 > n1 and n2 != n1 + 1: - ret[s] = 'expected %d, %d found' % (n1 + 1, n2) - self.lastMatch = text[s: e] - return ret -``` - -You can create new settings as well. Just follow the examples of existing rules and the value of settings are stored as `self.settings`. - -## Discussion - -You can share your opinions through [issues](https://github.com/SublimeText-Markdown/MarkdownEditing/issues). \ No newline at end of file diff --git a/list_back_links.py b/list_back_links.py deleted file mode 100644 index ee62e568..00000000 --- a/list_back_links.py +++ /dev/null @@ -1,22 +0,0 @@ -import sublime, sublime_plugin -import os, string - -try: - from MarkdownEditing.wiki_page import * -except ImportError: - from wiki_page import * - -try: - from MarkdownEditing.mdeutils import * -except ImportError: - from mdeutils import * - - -class ListBackLinksCommand(MDETextCommand): - def run(self, edit): - print("Running ListBackLinksCommand") - wiki_page = WikiPage(self.view) - - file_list = wiki_page.find_files_with_ref() - wiki_page.select_backlink(file_list) - diff --git a/macros/Balance Trailing Hashes.sublime-macro b/macros/Balance Trailing Hashes.sublime-macro new file mode 100644 index 00000000..a23bdd6c --- /dev/null +++ b/macros/Balance Trailing Hashes.sublime-macro @@ -0,0 +1,9 @@ +[ + {"command": "move_to", "args": {"to": "eol", "extend": false}}, + {"command": "insert_snippet", "args": {"contents": "${TM_CURRENT_LINE/^\\s*((?:>\\s*)*)(#+)(.*?)\\s*#*\\s*$/\n$1$2$3 $2\n$1/}"}}, + {"command": "move", "args": {"by": "lines", "forward": false}}, + {"command": "move", "args": {"by": "lines", "forward": false}}, + {"command": "run_macro_file", "args": {"file": "Packages/Default/Delete Line.sublime-macro"}}, + {"command": "move", "args": {"by": "lines", "forward": true}}, + {"command": "move_to", "args": {"to": "eol", "extend": false}} +] diff --git a/macros/Commit Critic Addition.sublime-macro b/macros/Commit Critic Addition.sublime-macro new file mode 100644 index 00000000..1e67d7d6 --- /dev/null +++ b/macros/Commit Critic Addition.sublime-macro @@ -0,0 +1,5 @@ +[ + {"command": "expand_selection", "args": {"to": "brackets"}}, + {"command": "expand_selection", "args": {"to": "brackets"}}, + {"command": "insert_snippet", "args": {"contents": "${SELECTION/\\{\\+\\+\\s?(.*?)\\s*\\+\\+\\}$/\\1/g}"}} +] diff --git a/macros/Commit Critic Deletion.sublime-macro b/macros/Commit Critic Deletion.sublime-macro new file mode 100644 index 00000000..2d272bbc --- /dev/null +++ b/macros/Commit Critic Deletion.sublime-macro @@ -0,0 +1,6 @@ +[ + {"command": "expand_selection", "args": {"to": "brackets"}}, + {"command": "expand_selection", "args": {"to": "brackets"}}, + {"command": "move", "args": {"by": "words", "extend": true, "forward": true}}, + {"command": "insert_snippet", "args": {"contents": "${SELECTION/\\{--.*--\\}[ \\t]*//g}"}} +] diff --git a/macros/Commit Critic Substitution.sublime-macro b/macros/Commit Critic Substitution.sublime-macro new file mode 100644 index 00000000..aab203f2 --- /dev/null +++ b/macros/Commit Critic Substitution.sublime-macro @@ -0,0 +1,5 @@ +[ + {"command": "expand_selection", "args": {"to": "brackets"}}, + {"command": "expand_selection", "args": {"to": "brackets"}}, + {"command": "insert_snippet", "args": {"contents": "${SELECTION/\\{~~\\s?(.*?)\\s?~>\\s?(.*?)\\s?~~\\}$/\\2/g}"}} +] diff --git a/macros/Convert List to Task Tab.sublime-macro b/macros/Convert List to Task Tab.sublime-macro new file mode 100644 index 00000000..1882209d --- /dev/null +++ b/macros/Convert List to Task Tab.sublime-macro @@ -0,0 +1,6 @@ +[ + {"command": "move", "args": {"by": "words", "forward": false, "extend": true}}, + {"command": "move", "args": {"by": "characters", "forward": true, "extend": true}}, + {"command": "left_delete"}, + {"command": "insert", "args": {"characters": " [ ]\t"}} +] diff --git a/macros/Convert List to Task.sublime-macro b/macros/Convert List to Task.sublime-macro new file mode 100644 index 00000000..a16b9ac0 --- /dev/null +++ b/macros/Convert List to Task.sublime-macro @@ -0,0 +1,6 @@ +[ + {"command": "move", "args": {"by": "words", "forward": false, "extend": true}}, + {"command": "move", "args": {"by": "characters", "forward": true, "extend": true}}, + {"command": "left_delete"}, + {"command": "insert", "args": {"characters": " [ ] "}} +] diff --git a/macros/Convert to Blockquote.sublime-macro b/macros/Convert to Blockquote.sublime-macro index 1ce81993..9544bd77 100644 --- a/macros/Convert to Blockquote.sublime-macro +++ b/macros/Convert to Blockquote.sublime-macro @@ -1,6 +1,6 @@ [ - {"command": "expand_selection", "args": {"to": "line"}}, - {"command": "move", "args": {"by": "characters", "extend": true, "forward": false}}, - {"command": "insert_snippet", "args": {"contents": "${TM_SELECTED_TEXT/^/> /gm}"}}, - {"command": "move_to", "args": {"extend": false, "to": "eol"}} + {"command": "expand_selection", "args": {"to": "line"}}, + {"command": "move", "args": {"by": "characters", "extend": true, "forward": false}}, + {"command": "insert_snippet", "args": {"contents": "${TM_SELECTED_TEXT/^/> /gm}"}}, + {"command": "move_to", "args": {"extend": false, "to": "eol"}} ] diff --git a/macros/Delete Left Right 2.sublime-macro b/macros/Delete Left Right 2.sublime-macro new file mode 100644 index 00000000..5acb387e --- /dev/null +++ b/macros/Delete Left Right 2.sublime-macro @@ -0,0 +1,6 @@ +[ + {"command": "left_delete" }, + {"command": "right_delete" }, + {"command": "left_delete" }, + {"command": "right_delete" } +] diff --git a/macros/Discard Critic Addition.sublime-macro b/macros/Discard Critic Addition.sublime-macro new file mode 100644 index 00000000..a6d1124d --- /dev/null +++ b/macros/Discard Critic Addition.sublime-macro @@ -0,0 +1,6 @@ +[ + {"command": "expand_selection", "args": {"to": "brackets"}}, + {"command": "expand_selection", "args": {"to": "brackets"}}, + {"command": "move", "args": {"by": "words", "extend": true, "forward": true}}, + {"command": "insert_snippet", "args": {"contents": "${SELECTION/\\{\\+\\+.*\\+\\+\\}[ \\t]*//g}"}} +] diff --git a/macros/Discard Critic Comment.sublime-macro b/macros/Discard Critic Comment.sublime-macro new file mode 100644 index 00000000..258cae16 --- /dev/null +++ b/macros/Discard Critic Comment.sublime-macro @@ -0,0 +1,6 @@ +[ + {"command": "expand_selection", "args": {"to": "brackets"}}, + {"command": "expand_selection", "args": {"to": "brackets"}}, + {"command": "move", "args": {"by": "words", "extend": true, "forward": true}}, + {"command": "insert_snippet", "args": {"contents": "${SELECTION/\\{>>.*<<\\}[ \\t]*//g}"}} +] diff --git a/macros/Discard Critic Deletion.sublime-macro b/macros/Discard Critic Deletion.sublime-macro new file mode 100644 index 00000000..52cc6a5d --- /dev/null +++ b/macros/Discard Critic Deletion.sublime-macro @@ -0,0 +1,5 @@ +[ + {"command": "expand_selection", "args": {"to": "brackets"}}, + {"command": "expand_selection", "args": {"to": "brackets"}}, + {"command": "insert_snippet", "args": {"contents": "${SELECTION/\\{--\\s?(.*?)\\s*--\\}$/\\1/g}"}} +] diff --git a/macros/Discard Critic Highlight.sublime-macro b/macros/Discard Critic Highlight.sublime-macro new file mode 100644 index 00000000..a49ed4e4 --- /dev/null +++ b/macros/Discard Critic Highlight.sublime-macro @@ -0,0 +1,6 @@ +[ + {"command": "expand_selection", "args": {"to": "brackets"}}, + {"command": "expand_selection", "args": {"to": "brackets"}}, + {"command": "move", "args": {"by": "words", "extend": true, "forward": true}}, + {"command": "insert_snippet", "args": {"contents": "${SELECTION/\\{==\\s?(.*?)\\s*==\\}[ \\t]*(.*)$/\\1\\2/g}"}} +] diff --git a/macros/Discard Critic Substitution.sublime-macro b/macros/Discard Critic Substitution.sublime-macro new file mode 100644 index 00000000..654fba54 --- /dev/null +++ b/macros/Discard Critic Substitution.sublime-macro @@ -0,0 +1,5 @@ +[ + {"command": "expand_selection", "args": {"to": "brackets"}}, + {"command": "expand_selection", "args": {"to": "brackets"}}, + {"command": "insert_snippet", "args": {"contents": "${SELECTION/\\{~~\\s?(.*?)\\s?~>\\s?(.*?)\\s?~~\\}$/\\1/g}"}} +] diff --git a/macros/Padded Headline.sublime-macro b/macros/Padded Headline.sublime-macro deleted file mode 100644 index 46345e1f..00000000 --- a/macros/Padded Headline.sublime-macro +++ /dev/null @@ -1,5 +0,0 @@ -[ - {"command": "expand_selection", "args": {"to": "line"}}, - {"command": "insert_snippet","args":{"contents": "${0:${SELECTION/(^#+ | #+$)//gm}}"}}, - {"command": "move", "args": {"by": "characters", "forward": false, "extend": true}} -] diff --git a/macros/Remove Empty Blockquote Line.sublime-macro b/macros/Remove Empty Blockquote Line.sublime-macro new file mode 100644 index 00000000..9e727ffb --- /dev/null +++ b/macros/Remove Empty Blockquote Line.sublime-macro @@ -0,0 +1,5 @@ +[ + {"command": "run_macro_file", "args": {"file": "Packages/Default/Delete Line.sublime-macro"}}, + {"command": "insert", "args": {"characters": "\n"}}, + {"command": "move", "args": {"by": "characters", "forward": false}} +] diff --git a/macros/Remove Empty List Item.sublime-macro b/macros/Remove Empty List Item.sublime-macro index 06c4d655..b387cd2d 100644 --- a/macros/Remove Empty List Item.sublime-macro +++ b/macros/Remove Empty List Item.sublime-macro @@ -1,7 +1,7 @@ [ - // {"command": "expand_selection", "args": {"to": "line"} }, - // {"command": "left_delete"} - {"command": "run_macro_file", "args": {"file": "Packages/Default/Delete Line.sublime-macro"}}, - {"command": "insert", "args": {"characters": "\n"}}, - {"command": "move", "args": {"by": "characters", "forward": false}} + {"command": "move_to", "args": {"to": "eol", "extend": false}}, + {"command": "insert_snippet", "args": {"contents": "${TM_CURRENT_LINE/^\\s*((?:>\\s*)*).*/\n$1/}"}}, + {"command": "move", "args": {"by": "lines", "forward": false}}, + {"command": "run_macro_file", "args": {"file": "Packages/Default/Delete Line.sublime-macro"}}, + {"command": "move_to", "args": {"to": "eol", "extend": false}} ] diff --git a/macros/Remove Trailing Hashes.sublime-macro b/macros/Remove Trailing Hashes.sublime-macro new file mode 100644 index 00000000..73edc998 --- /dev/null +++ b/macros/Remove Trailing Hashes.sublime-macro @@ -0,0 +1,9 @@ +[ + {"command": "move_to", "args": {"to": "eol", "extend": false}}, + {"command": "insert_snippet", "args": {"contents": "${TM_CURRENT_LINE/^\\s*((?:>\\s*)*)(#+)(.*?)\\s*#*\\s*$/\n$1$2$3\n$1/}"}}, + {"command": "move", "args": {"by": "lines", "forward": false}}, + {"command": "move", "args": {"by": "lines", "forward": false}}, + {"command": "run_macro_file", "args": {"file": "Packages/Default/Delete Line.sublime-macro"}}, + {"command": "move", "args": {"by": "lines", "forward": true}}, + {"command": "move_to", "args": {"to": "eol", "extend": false}} +] diff --git a/macros/Skip Closing Character.sublime-macro b/macros/Skip Closing Character.sublime-macro deleted file mode 100644 index a6b858fa..00000000 --- a/macros/Skip Closing Character.sublime-macro +++ /dev/null @@ -1,3 +0,0 @@ -[ - {"command": "move", "args": {"by": "characters", "forward": true}} -] diff --git a/macros/Start List Item Tab.sublime-macro b/macros/Start List Item Tab.sublime-macro index 08a563ec..da31d791 100644 --- a/macros/Start List Item Tab.sublime-macro +++ b/macros/Start List Item Tab.sublime-macro @@ -1,4 +1,4 @@ [ - {"command": "right_delete" }, - {"command": "insert", "args": {"characters": "\t"} } + {"command": "right_delete" }, + {"command": "insert", "args": {"characters": "\t"} } ] diff --git a/macros/Start List Item.sublime-macro b/macros/Start List Item.sublime-macro index 8a5408a7..d9cb40cb 100644 --- a/macros/Start List Item.sublime-macro +++ b/macros/Start List Item.sublime-macro @@ -1,4 +1,4 @@ [ - {"command": "right_delete" }, - {"command": "insert", "args": {"characters": " "} } + {"command": "right_delete" }, + {"command": "insert", "args": {"characters": " "} } ] diff --git a/macros/Transform Word - Bold (Asterisk).sublime-macro b/macros/Transform Word - Bold (Asterisk).sublime-macro new file mode 100644 index 00000000..205d8138 --- /dev/null +++ b/macros/Transform Word - Bold (Asterisk).sublime-macro @@ -0,0 +1,5 @@ +[ + {"command": "expand_selection", "args": {"to": "word"}}, + {"command": "insert_snippet", "args": {"contents": "**${SELECTION/^\\*\\*|^__|\\*\\*$|__$//g}**"}}, + {"command": "move", "args": {"by": "words", "forward": false}} +] diff --git a/macros/Transform Word - Bold (Underscore).sublime-macro b/macros/Transform Word - Bold (Underscore).sublime-macro new file mode 100644 index 00000000..d5af16db --- /dev/null +++ b/macros/Transform Word - Bold (Underscore).sublime-macro @@ -0,0 +1,5 @@ +[ + {"command": "expand_selection", "args": {"to": "word"}}, + {"command": "insert_snippet", "args": {"contents": "__${SELECTION/^\\*\\*|^__|\\*\\*$|__$//g}__"}}, + {"command": "move", "args": {"by": "words", "forward": false}} +] diff --git a/macros/Transform Word - Bold.sublime-macro b/macros/Transform Word - Bold.sublime-macro deleted file mode 100644 index 2f2c9ea2..00000000 --- a/macros/Transform Word - Bold.sublime-macro +++ /dev/null @@ -1,4 +0,0 @@ -[ - {"command": "custom_find_under_expand"}, - {"command": "insert_snippet", "args": {"contents": "${MD_BOLD_MARKER}${SELECTION/(^[\\*_]*|[\\*_]*$)//g}${MD_BOLD_MARKER}"}} -] diff --git a/macros/Transform Word - Critic Deletion.sublime-macro b/macros/Transform Word - Critic Deletion.sublime-macro new file mode 100644 index 00000000..a582ad8b --- /dev/null +++ b/macros/Transform Word - Critic Deletion.sublime-macro @@ -0,0 +1,4 @@ +[ + {"command": "expand_selection", "args": {"to": "word"}}, + {"command": "insert_snippet", "args": {"name": "Packages/MarkdownEditing/snippets/Critic Deletion.sublime-snippet"}} +] diff --git a/macros/Transform Word - Critic Highlight.sublime-macro b/macros/Transform Word - Critic Highlight.sublime-macro new file mode 100644 index 00000000..6a6f9f8b --- /dev/null +++ b/macros/Transform Word - Critic Highlight.sublime-macro @@ -0,0 +1,4 @@ +[ + {"command": "expand_selection", "args": {"to": "word"}}, + {"command": "insert_snippet", "args": {"name": "Packages/MarkdownEditing/snippets/Critic Highlight.sublime-snippet"}} +] diff --git a/macros/Transform Word - Critic Substitution.sublime-macro b/macros/Transform Word - Critic Substitution.sublime-macro new file mode 100644 index 00000000..3fe5fd3c --- /dev/null +++ b/macros/Transform Word - Critic Substitution.sublime-macro @@ -0,0 +1,4 @@ +[ + {"command": "expand_selection", "args": {"to": "word"}}, + {"command": "insert_snippet", "args": {"name": "Packages/MarkdownEditing/snippets/Critic Substitution.sublime-snippet"}} +] diff --git a/macros/Transform Word - Italic (Asterisk).sublime-macro b/macros/Transform Word - Italic (Asterisk).sublime-macro new file mode 100644 index 00000000..452db80a --- /dev/null +++ b/macros/Transform Word - Italic (Asterisk).sublime-macro @@ -0,0 +1,5 @@ +[ + {"command": "expand_selection", "args": {"to": "word"}}, + {"command": "insert_snippet", "args": {"contents": "*${SELECTION/^(\\*{2}|_{2})?([*_])(.+)([*_])(\\*{2}|_{2})?$/$1$3$1/g}*"}}, + {"command": "move", "args": {"by": "words", "forward": false}} +] diff --git a/macros/Transform Word - Italic (Underscore).sublime-macro b/macros/Transform Word - Italic (Underscore).sublime-macro new file mode 100644 index 00000000..7491d21a --- /dev/null +++ b/macros/Transform Word - Italic (Underscore).sublime-macro @@ -0,0 +1,5 @@ +[ + {"command": "expand_selection", "args": {"to": "word"}}, + {"command": "insert_snippet", "args": {"contents": "_${SELECTION/^(\\*{2}|_{2})?([*_])(.+)([*_])(\\*{2}|_{2})?$/$1$3$1/g}_"}}, + {"command": "move", "args": {"by": "words", "forward": false}} +] diff --git a/macros/Transform Word - Italic.sublime-macro b/macros/Transform Word - Italic.sublime-macro deleted file mode 100644 index e1cd8db7..00000000 --- a/macros/Transform Word - Italic.sublime-macro +++ /dev/null @@ -1,4 +0,0 @@ -[ - {"command": "custom_find_under_expand"}, - {"command": "insert_snippet", "args": {"contents": "${MD_ITALIC_MARKER}${SELECTION/(^[\\*_]*|[\\*_]*$)//g}${MD_ITALIC_MARKER}"}} -] diff --git a/macros/Transform Word - Unbold Unitalicize.sublime-macro b/macros/Transform Word - Unbold Unitalicize.sublime-macro deleted file mode 100644 index 97b69721..00000000 --- a/macros/Transform Word - Unbold Unitalicize.sublime-macro +++ /dev/null @@ -1,4 +0,0 @@ -[ - {"command": "custom_find_under_expand"}, - {"command": "insert_snippet", "args": {"contents": "${SELECTION/(^[*_]*|[*_]*$)//g}"}} -] diff --git a/macros/Transform Word - Unbold.sublime-macro b/macros/Transform Word - Unbold.sublime-macro new file mode 100644 index 00000000..bb5b14fb --- /dev/null +++ b/macros/Transform Word - Unbold.sublime-macro @@ -0,0 +1,5 @@ +[ + {"command": "expand_selection", "args": {"to": "scope"}}, + {"command": "insert_snippet", "args": {"contents": "${SELECTION/^\\*\\*|^__|\\*\\*$|__$//g}"}}, + {"command": "move", "args": {"by": "words", "forward": false}} +] diff --git a/macros/Transform Word - Unitalicize.sublime-macro b/macros/Transform Word - Unitalicize.sublime-macro new file mode 100644 index 00000000..b6db6d9d --- /dev/null +++ b/macros/Transform Word - Unitalicize.sublime-macro @@ -0,0 +1,5 @@ +[ + {"command": "expand_selection", "args": {"to": "scope"}}, + {"command": "insert_snippet", "args": {"contents": "${SELECTION/^(?:(\\*{2}|_{2})?([*_])|([*_])(\\*{2}|_{2})?)(\\S(?:.*\\S))(?:(\\2)(\\1)|(\\4)?(\\3))$/$1$4$5$7$8/g}"}}, + {"command": "move", "args": {"by": "words", "forward": false}} +] diff --git a/make.cmd b/make.cmd new file mode 100644 index 00000000..e275d771 --- /dev/null +++ b/make.cmd @@ -0,0 +1,61 @@ +:: This script is used to +:: 1. setup python .venv with requirements installed +:: 2. run all development tasks within that .venv +@echo off +setlocal +chcp 65001 >nul +pushd %~dp0 + +if /i "%1" == "init" goto INIT +if /i "%1" == "docs" goto DOCS +if /i "%1" == "deploy-docs" goto DEPLOY-DOCS +if /i "%1" == "serve" goto SERVE +if /i "%1" == "lint" goto LINT +goto :usage + +:INIT + if not exist .venv python -m venv .venv + call :venv + call python -m pip install --upgrade pip + call pip install --upgrade -r docs\requirements.txt + call pip install --upgrade -r tests\requirements.txt + goto :eof + +:DOCS + call :venv + mkdocs build + goto :eof + +:DEPLOY-DOCS + call :venv + mkdocs gh-deploy + goto :eof + +:SERVE + call :venv + call explorer http://localhost:8000 + mkdocs serve + goto :eof + +:LINT + call :venv + black --check . + flake8 + goto :eof + +:VENV + call .venv\scripts\activate.bat + if "%VIRTUAL_ENV%" neq ".venv" exit /b 1 + goto :eof + +:USAGE + echo USAGE: + echo. + echo make ^[init^|docs^|gh-pages^|serve^|lint^] + echo. + echo init -- setup .venv and install requirements. + echo docs -- build documentation + echo deploy-docs -- build documentation and publish on Github Pages + echo serve -- build documentation and serve via development server + echo lint -- run black, flake8 and pytest + goto :eof diff --git a/make_page_reference.py b/make_page_reference.py deleted file mode 100644 index d8bb5884..00000000 --- a/make_page_reference.py +++ /dev/null @@ -1,35 +0,0 @@ -import sublime, sublime_plugin -import os, string - -try: - from MarkdownEditing.wiki_page import * -except ImportError: - from wiki_page import * - -try: - from MarkdownEditing.mdeutils import * -except ImportError: - from mdeutils import * - - -class MakePageReferenceCommand(MDETextCommand): - def is_visible(self): - """Return True if cursor is on a wiki page reference.""" - for sel in self.view.sel(): - scopes = self.view.scope_name(sel.b).split(" ") - if 'meta.link.wiki.markdown' in scopes: - return False - - return True - - def run(self, edit): - print("Running MakePageReferenceCommand") - wiki_page = WikiPage(self.view) - - word_region = wiki_page.select_word_at_cursor() - file_list = wiki_page.find_matching_files(word_region) - - wiki_page.make_page_reference(edit, word_region) - - if len(file_list) > 1: - wiki_page.show_quick_list(file_list) diff --git a/mdeutils.py b/mdeutils.py deleted file mode 100644 index 8bbf27be..00000000 --- a/mdeutils.py +++ /dev/null @@ -1,18 +0,0 @@ -import sublime -import sublime_plugin - - -def view_is_markdown(view): - if len(view.sel()) > 0: - return len(view.sel()) > 0 and bool(view.score_selector(view.sel()[0].a, "text.html.markdown")) - else: - return False - - -class MDETextCommand(sublime_plugin.TextCommand): - - def is_enabled(self): - return view_is_markdown(self.view) - - def is_visible(self): - return view_is_markdown(self.view) diff --git a/messages.json b/messages.json index f7dc2572..c35ddd72 100644 --- a/messages.json +++ b/messages.json @@ -1,29 +1,30 @@ { - "install": "README.md", - "2.0.0": "messages/2.0.0.txt", - "2.0.1": "messages/2.0.1.md", - "2.0.2": "messages/2.0.2.md", - "2.0.3": "messages/2.0.3.md", - "2.0.4": "messages/2.0.4.md", - "2.0.5": "messages/2.0.5.md", - "2.0.6": "messages/2.0.6.md", - "2.0.7": "messages/2.0.7.md", - "2.0.8": "messages/2.0.8.md", - "2.0.9": "messages/2.0.9.md", - "2.1.0": "messages/2.1.0.md", - "2.1.1": "messages/2.1.1.md", - "2.1.2": "messages/2.1.2.md", - "2.1.3": "messages/2.1.3.md", - "2.1.4": "messages/2.1.4.md", - "2.1.5": "messages/2.1.5.md", - "2.1.6": "messages/2.1.6.md", - "2.1.7": "messages/2.1.7.md", - "2.1.8": "messages/2.1.8.md", - "2.1.9": "messages/2.1.9.md", - "2.2.0": "messages/2.2.0.md", - "2.2.1": "messages/2.2.1.md", - "2.2.2": "messages/2.2.2.md", - "2.2.3": "messages/2.2.3.md", - "2.2.4": "messages/2.2.4.md", - "2.2.10": "messages/2.2.10.md" + "install": "messages/install.md", + "2.0.0": "messages/2.0.0.txt", + "2.0.1": "messages/2.0.1.md", + "2.0.2": "messages/2.0.2.md", + "2.0.3": "messages/2.0.3.md", + "2.0.4": "messages/2.0.4.md", + "2.0.5": "messages/2.0.5.md", + "2.0.6": "messages/2.0.6.md", + "2.0.7": "messages/2.0.7.md", + "2.0.8": "messages/2.0.8.md", + "2.0.9": "messages/2.0.9.md", + "2.1.0": "messages/2.1.0.md", + "2.1.1": "messages/2.1.1.md", + "2.1.2": "messages/2.1.2.md", + "2.1.3": "messages/2.1.3.md", + "2.1.4": "messages/2.1.4.md", + "2.1.5": "messages/2.1.5.md", + "2.1.6": "messages/2.1.6.md", + "2.1.7": "messages/2.1.7.md", + "2.1.8": "messages/2.1.8.md", + "2.1.9": "messages/2.1.9.md", + "2.2.0": "messages/2.2.0.md", + "2.2.1": "messages/2.2.1.md", + "2.2.2": "messages/2.2.2.md", + "2.2.3": "messages/2.2.3.md", + "2.2.4": "messages/2.2.4.md", + "2.2.10": "messages/2.2.10.md", + "3.0.0": "messages/3.0.0.md" } diff --git a/messages/2.2.8.md b/messages/2.2.8.md new file mode 100644 index 00000000..c6eb0603 --- /dev/null +++ b/messages/2.2.8.md @@ -0,0 +1,21 @@ +# MarkdownEditing 2.2.8 Changelog + +Your _MarkdownEditing_ plugin is updated. Enjoy new version. For any type of +feedback you can use [GitHub issues][issues]. + +## Bug Fixes + +* Some theme display bugs are fixed. + - Strikethroughs are highlighted properly. + - Link texts are highlighted properly. + +## New Features + +* Tab/shift+tab on the beginning of the line of a list item will correctly indent/unindent that item. +* Support AutoHotkey AHK fenced code (if supported syntax is installed) + +## Changes + +* Default four color schemes are renamed from '.tmTheme' extension to '.sublime-color-scheme'. Sublime Text seems to be smart enough to redirect .tmTheme files to .sublime-color-scheme files in settings if possible. + +[issues]: https://github.com/SublimeText-Markdown/MarkdownEditing/issues diff --git a/messages/3.0.0.md b/messages/3.0.0.md new file mode 100644 index 00000000..162c0e06 --- /dev/null +++ b/messages/3.0.0.md @@ -0,0 +1,186 @@ +# MarkdownEditing 3.0.0 Changelog + +Your _MarkdownEditing_ plugin is updated. Enjoy new version. For any type of +feedback you can use [GitHub issues][issues]. + +This is a major release with several breaking changes, which are required to +fix issues, avoid possible confilcts with other packages and enhance overall +handling of user settings. + +Please visit [User Guide][UserGuide] to learn more about the full set of features +and how to use them. + +If you defined custom key bindings or settings you might need to check and +adjust those as commands have been renamed and all preferencesare moved to +Preferences.sublime-settings. + +A set of tips is listed in the [Troubleshooting][] section of the [User Guide][UserGuide]. + + +## Bug Fixes + +### Behavior Fixes + +* changing heading levels no longer requires text to be selected (fixes #78) +* changing heading levels works within block quotes +* changing heading levels no longer adds hashmarkers in the middle of a line +* auto matching heading hash tags on `enter` now works in blockquotes +* `mde_complete_underlined_headings` no longer prevents tab after `-` in new lists (fixes #177) +* `ctrl+alt+s` is disabled by default to avoid confilcts (fixes #178) +* automatic centering is enabled only if `mde.keep_centered` is `True` (fixes #259) +* reassign syntax of open markdown files after install or before uninstall (fixes #216,fixes #485) +* reset syntax specific `color_scheme` before plugin is uninstalled (fixes #493) +* internal linter now ignores front-matter (fixes #498) +* improve strikethrough color scheme rules with regards to punctuation (fixes #534) +* fix `shift+tab` not unindenting list items in some situations (fixes #545) +* fix `shift+tab` folding instead of unindenting list (fixes #552) +* fix bold/italic via `alt+b`/`alt+i` if both marker types are set to `*` (fixes #562) +* linter rule md028 correctly detects empty lines between blockquotes (fixes #564) +* linter rule md027 no longer triggers for indented lists in blockquotes (fixes #565) +* adding footnotes no longer fails if textual footnotes exist (fixes #586) +* global color scheme is the default and can optionally be replaced (fixes #436,fixes #567, fixes #595) +* avoid possible command naming conflicts with other packages (fixes #606) +* hitting `enter` after heading adds correct number of trailing hashes + if `mde.match_heading_hashes` is `true` even if some exist already. +* hitting `enter` after heading removes trailing hashes + if `mde.match_heading_hashes` is `false`. +* hitting `enter` in block quotes correctly adds list and task items +* hitting `enter` adds new lists/tasks/quotes if auto completion is visisble and + `"setting.auto_complete_commit_on_tab": true` +* hitting `enter` after reference definitions no longer adds duplicates +* hitting `enter` after empty list or GFM task items removes them without terminating blockquotes +* hitting `enter` after empty blockquotes removes the blockquote markers +* disables auto-pairing of `*`, `_`, `` ` ``, `<`, ... within `` tags +* indent/unindent list items now works within blockquotes +* `tab` and `shift+tab` correctly select next/previous field of snippets + instead of indenting/undindenting lists or folding sections + +### Syntax Fixes + +Markdown syntax is backported from ST4114 to a ST3 compatible version, which provides a lot of +fixes and improvements for ST3176+. + +* highlight multiline bold/italics (fixes #103) +* highlight code blocks in lists (fixes #122) +* highlight blockquote in lists (fixes #123) +* add table syntax (fixes #124) +* add critic markup (fixes #144) +* text and urls inside itallic (bold) markup work correctly (fixes #246) +* striked urls no longer break highlighting (fixes #263) +* highlight inline bold, italic and raw code blocks in link and image descriptions (fixes #404) +* line-breaks within Markdown comments no longer break highlighting (fixes #409) +* scope hard line breaks and update color schemes (fixes #470) +* prevent "Apparent recursion" error by embedding syntaxes in fenced code blocks (fixes #533) +* strikethrough followed by no space no longer disables highlighting (fixes #537) +* correctly scope bold parts of a word (fixes #553) +* don't highlight words starting with hashtag as heading (fixes #572) +* ignore info string after language identifier of code fences (fixes #577) +* scope punctuation of fenced code blocks (fixes #612) + +## New Features + +* heading levels can be changed incrementally via ctrl+alt+, + and ctrl+alt+. (fixes #78) +* _Toggle Centered Line_ added to Command Palette (fixes #118) +* a new setting `mde.list_align_text` controls whether list item text is alignt to indention levels +* key binding (`alt+t`) to create new or convert empty list item to gfm task +* key binding (`alt+x`) to toggle task lists (fixes #589) +* Color scheme quick panel lists all _MarkdownEditor-.sublime-color-scheme_ files (fixes #563) +* fenced codeblocks learned to highlight DOS Batch syntax + - Ada syntax + - DOS batch syntax + - Dart syntax + - Docker syntax + - Elixir syntax + - GraphQL syntax + - INI syntax + - Jade syntax + - JSX syntax + - Julia syntax + - Kotlin syntax + - Matlab syntax + - Mermaid syntax + - NIM/NIX syntax + - PowerShell syntax + - R syntax (fixes #569) + - STATA syntax (fixes #560) + - TOML syntax + - TSX syntax +* key bindings and snippets to easily insert, accept or reject critic markup + - press `alt+c, alt+a` to insert addition + - press `alt+c, alt+d` to insert deletion + - press `alt+c, alt+h` to insert highlight + - press `alt+c, alt+s` to insert substitution + - press `alt+c, alt+c` to insert comment + - press `alt+enter` to accept critic + - press `alt+backspace` to reject critic + +## Changes + +* All syntaxes use sublime-syntax format (fixes #324) +* Requires ST 3176+ (closes #463) +* Opt-in to ST4's python3.8 plugin host +* Reorganize all python modules in a _plugins_ sub directory +* Merge several python modules to group functions logically +* Removed most syntax specific settings (fixes #209, fixes #501, fixes #509) +* Settings are displayed side-by-side (fixes #609) +* Settings are now placed in Preferences.sublime-settings +* Reorganize key bindings to group them by logical function +* MultiMarkdown is converted to sublime-syntax format +* Bold/Italics style is now configured via Preferences + (removed _Bold and Italic Markers.tmPreferences_) +* The `mde_fold_section` command now respects previously set folding level + (Results in more consistend and logical behavior when combined wth `mde_fold_all_sections`) +* new commands: + - `mde_change_headings_level` + - `mde_fold_links` + - `mde_match_heading_hashes` + - `mde_toggle_centered_line` + - `mde_toggle_task_list_item` + - `unindent_list_item` replaces `indent_list_item(reverse=True)` + and `indent_list_multiitem(reverse=True)` +* removed commands: + - `indent_list_multiitem` +* renamed commands (all commands are prefixed with `mde_`): + - `complete_underlined_header` -> `mde_complete_underlined_headings` + - `convert_inline_link_to_reference` -> `mde_convert_inline_link_to_reference` + - `convert_inline_links_to_references` -> `mde_convert_inline_links_to_references` + - `convert_to_atx` -> `mde_convert_underlined_headings_to_atx` + - `deindent_quote` -> `mde_unindent_quote` + - `fix_all_underlined_headers` -> `mde_fix_underlined_headings` + - `fold_all_sections` -> `mde_fold_all_sections` + - `fold_section` -> `mde_fold_section` + - `gather_missing_footnotes` -> `mde_gather_missing_footnotes` + - `gather_missing_link_markers` -> `mde_gather_missing_link_markers` + - `goto_next_heading` -> `mde_goto_next_heading` + - `goto_previous_heading` -> `mde_goto_previous_heading` + - `indent_list_item` -> `mde_indent_list_item` (is used for all items/situations) (fixes #530) + - `indent_quote` -> `mde_indent_quote` + - `list_back_links` -> `mde_list_back_links` + - `magic_footnotes` -> `mde_magic_footnotes` + - `make_page_reference` -> `mde_make_page_reference` + - `markdown_lint` -> `mde_markdown_lint` + - `markdown_lint_mdl` -> `mde_markdown_lint_mdl` + - `mde_color_activate` -> `mde_select_color_scheme` + - `number_list` -> `mde_number_list` + - `number_list_reference` -> `mde_add_numbered_reference_definition` + - `open_home_page` -> `mde_open_home_page` + - `open_journal` -> `mde_open_journal` + - `open_page` -> `mde_open_page` + - `reference_delete_reference` -> `mde_reference_delete_reference` + - `reference_jump` -> `mde_reference_jump` + - `reference_new_footnote` -> `mde_reference_new_footnote` + - `reference_new_image` -> `mde_reference_new_image` + - `reference_new_inline_image` -> `mde_reference_new_inline_image` + - `reference_new_inline_link` -> `mde_reference_new_inline_link` + - `reference_new_reference` -> `mde_reference_new_reference` + - `reference_organize` -> `mde_reference_organize` + - `show_fold_all_sections` -> `mde_show_fold_all_sections` + - `switch_list_bullet_type` -> `mde_switch_list_bullet_type` + - `unfold_all_sections` -> `mde_unfold_all_sections` +* renamed settings: + - `mde.match_haeder_hash` -> `mde.match_heading_hashes` + +[issues]: https://github.com/SublimeText-Markdown/MarkdownEditing/issues +[UserGuide]: https://sublimetext-markdown.github.io/MarkdownEditing +[Troubleshooting]: https://sublimetext-markdown.github.io/MarkdownEditing/troubleshooting diff --git a/messages/install.md b/messages/install.md new file mode 100644 index 00000000..f68975c0 --- /dev/null +++ b/messages/install.md @@ -0,0 +1,16 @@ +# MarkdownEditing + +Thanks for installing MarkdownEditing. + +This package provides + +* useful Markdown editing features for Sublime Text +* color schemes optimized for writing +* robust syntax definitions for + - Standard Markdown + - Github flavored Markdown + - MultiMarkdown + +User Guide is available at https://sublimetext-markdown.github.io/MarkdownEditing + +Bugs or feedback via https://github.com/SublimeText-Markdown/MarkdownEditing/issues diff --git a/mkdocs.yml b/mkdocs.yml new file mode 100644 index 00000000..d391bcf6 --- /dev/null +++ b/mkdocs.yml @@ -0,0 +1,55 @@ +%YAML 1.2 +--- +site_name: "MarkdownEditing" +site_description: MarkdownEditing User Manual +site_author: DeathAxe +site_url: "https://sublimetext-markdown.github.io/MarkdownEditing" +repo_url: "https://github.com/SublimeText-Markdown/MarkdownEditing" +docs_dir: "docs" + +nav: + - Home: "index.md" + - Installation: "install.md" + - Usage: "usage.md" + - Linting: "linting.md" + - Configuration: "config.md" + - Troubleshooting: "troubleshooting.md" + +extra: + collapse_toc: true + +extra_css: + - "css/styles.css" + +theme: + name: cinder + features: + - navigation.tabs + +plugins: + - minify: + minify_html: true + +markdown_extensions: + - markdown.extensions.admonition: + - markdown.extensions.footnotes: + - pymdownx.superfences: + preserve_tabs: true + - pymdownx.highlight: + linenums_style: pymdownx-inline + - pymdownx.inlinehilite: + - pymdownx.escapeall: + hardbreak: True + nbsp: True + - pymdownx.tasklist: + custom_checkbox: true + - pymdownx.progressbar: + - pymdownx.arithmatex: + - pymdownx.mark: + - pymdownx.tilde: + - pymdownx.striphtml: + - pymdownx.keys: + separator: "\uff0b" + - pymdownx.details: + - pymdownx.tabbed: + - pymdownx.saneheaders: diff --git a/numbered_list.py b/numbered_list.py deleted file mode 100644 index ebfe8a81..00000000 --- a/numbered_list.py +++ /dev/null @@ -1,42 +0,0 @@ -import sublime_plugin -import re -try: - from MarkdownEditing.mdeutils import * -except ImportError: - from mdeutils import * - - -class NumberListCommand(MDETextCommand): - - def run(self, edit): - view = self.view - sel = view.sel()[0] - text = view.substr(view.full_line(sel)) - num = re.search('\d', text).start() - dot = text.find(".") - additional_spaces = re.search(r"^\s*", text[dot+1:]).group() - increment = 0 - if self.view.settings().get('mde.auto_increment_ordered_list_number', True): - increment = 1 - if num == 0: - view.erase(edit, sel) - view.insert(edit, sel.begin(), "\n%d.%s" % (int(text[:dot]) + increment, additional_spaces)) - else: - view.erase(edit, sel) - view.insert(edit, sel.begin(), "\n%s%d.%s" % (text[:num], int(text[num:dot]) + increment, additional_spaces)) - - -class NumberListReferenceCommand(MDETextCommand): - - def run(self, edit): - view = self.view - sel = view.sel()[0] - text = view.substr(view.full_line(sel)) - num = re.search('\d', text).start() - dot = text.find("]") - if num == 0: - view.erase(edit, sel) - view.insert(edit, sel.begin(), "\n%d]: " % (int(text[:dot]) + 1,)) - else: - view.erase(edit, sel) - view.insert(edit, sel.begin(), "\n%s%d]: " % (text[:num], int(text[num:dot]) + 1)) diff --git a/open_home_page.py b/open_home_page.py deleted file mode 100644 index 109b922d..00000000 --- a/open_home_page.py +++ /dev/null @@ -1,22 +0,0 @@ -import sublime, sublime_plugin -import os, string -import re - -try: - from MarkdownEditing.wiki_page import * -except ImportError: - from wiki_page import * - -try: - from MarkdownEditing.mdeutils import * -except ImportError: - from mdeutils import * - - -class OpenHomePageCommand(MDETextCommand): - def run(self, edit): - print("Running OpenHomePageCommand") - home_page = self.view.settings().get("mde.wikilinks.homepage", DEFAULT_HOME_PAGE) - - wiki_page = WikiPage(self.view) - wiki_page.select_page(home_page) diff --git a/open_journal.py b/open_journal.py deleted file mode 100644 index ebb4c311..00000000 --- a/open_journal.py +++ /dev/null @@ -1,25 +0,0 @@ -import sublime, sublime_plugin -import os, string -import re - -from datetime import date - -try: - from MarkdownEditing.wiki_page import * -except ImportError: - from wiki_page import * - -try: - from MarkdownEditing.mdeutils import * -except ImportError: - from mdeutils import * - - -class OpenJournalCommand(MDETextCommand): - def run(self, edit): - print("Running OpenJournalCommand") - today = date.today() - name = today.strftime('%Y-%m-%d') - - wiki_page = WikiPage(self.view) - wiki_page.select_page(name) diff --git a/open_page.py b/open_page.py deleted file mode 100644 index 066022c0..00000000 --- a/open_page.py +++ /dev/null @@ -1,52 +0,0 @@ - -import sublime, sublime_plugin -import os, string -import re - - -try: - from MarkdownEditing.wiki_page import * -except ImportError: - from wiki_page import * - -try: - from MarkdownEditing.mdeutils import * -except ImportError: - from mdeutils import * - - -class OpenPageCommand(MDETextCommand): - def is_visible(self): - """Return True if cursor is on a wiki page reference.""" - for sel in self.view.sel(): - scopes = self.view.scope_name(sel.b).split(" ") - if 'meta.link.wiki.markdown' in scopes: - return True - - return False - - def run(self, edit): - print("Running OpenPageCommand") - wiki_page = WikiPage(self.view) - - sel_region = self.get_selected() - if sel_region: - wiki_page.select_word_at_cursor() - - region = sublime.Region(sel_region.begin(), sel_region.begin()) - file_list = wiki_page.find_matching_files(region) - - if len(file_list) > 1: - wiki_page.show_quick_list(file_list) - else: - name = wiki_page.identify_page_at_cursor() - wiki_page.select_page(name) - - - def get_selected(self): - selection = self.view.sel() - for region in selection: - return region - - return None - diff --git a/plugin.py b/plugin.py new file mode 100644 index 00000000..d8a8d334 --- /dev/null +++ b/plugin.py @@ -0,0 +1,117 @@ +"""Load and Unload all MarkdownEditing modules. + +This module exports __all__ modules, which Sublime Text needs to know about. +""" +import sublime + +if int(sublime.version()) < 3176: + print(__package__ + " requires ST3 3176+") +else: + import sys + + # clear modules cache if package is reloaded (after update?) + prefix = __package__ + "." # don't clear the base package + for module_name in [ + module_name + for module_name in sys.modules + if module_name.startswith(prefix) and module_name != __name__ + ]: + del sys.modules[module_name] + prefix = None + + # import all published Commands and EventListeners + from .plugins.bootstrap import ( + on_after_install, + on_before_uninstall, + ) + from .plugins.color_schemes import ( + MdeSelectColorSchemeCommand, + ) + from .plugins.folding import ( + MdeFoldAllSectionsCommand, + MdeFoldLinksCommand, + MdeFoldLinksListener, + MdeFoldSectionCommand, + MdeFoldSectionContextCommand, + MdeShowFoldAllSectionsCommand, + MdeUnfoldAllSectionsCommand, + MdeUnfoldSectionContextCommand, + ) + from .plugins.footnotes import ( + MdeGatherMissingFootnotesCommand, + MdeGotoFootnoteDefinitionCommand, + MdeGotoFootnoteReferenceCommand, + MdeInsertFootnoteCommand, + MdeMagicFootnotesCommand, + MdeSortFootnotesCommand, + MdeSwitchToFromFootnoteCommand, + MdeMarkFootnotesListener, + ) + from .plugins.headings import ( + MdeChangeHeadingsLevelCommand, + MdeCompleteUnderlinedHeadingsCommand, + MdeConvertUnderlinedHeadingsToAtxCommand, + MdeFixUnderlinedHeadingsCommand, + MdeGotoNextHeadingCommand, + MdeGotoPreviousHeadingCommand, + MdeMatchHeadingHashesCommand, + MdeMatchHeadingHashesDetector, + MdeUnsavedViewNameSetter, + ) + from .plugins.lists import ( + MdeIndentListItemCommand, + MdeUnindentListItemCommand, + MdeNumberListCommand, + MdeSwitchListBulletTypeCommand, + MdeToggleTaskListItemCommand, + MdeJoinLines, + ) + from .plugins.lint import ( + MdeMarkdownLintCommand, + MdeMarkdownLintMdlCommand, + ) + from .plugins.logging import ( + load_logger, + unload_logger + ) + from .plugins.quotes import ( + MdeIndentQuote, + MdeUnindentQuote, + ) + from .plugins.references import ( + MdeConvertInlineLinksToReferencesCommand, + MdeConvertInlineLinkToReferenceCommand, + MdeGatherMissingLinkMarkersCommand, + MdeReferenceDeleteReferenceCommand, + MdeReferenceJumpCommand, + MdeReferenceJumpContextCommand, + MdeReferenceNewFootnoteCommand, + MdeReferenceNewImageCommand, + MdeReferenceNewInlineImageCommand, + MdeReferenceNewInlineLinkCommand, + MdeReferenceNewReferenceCommand, + MdeReferenceOrganizeCommand, + MdeAddNumberedReferenceDefinitionCommand, + MdeReferenceCompletionsProvider, + ) + from .plugins.view import ( + MdeReplaceSelectedCommand, + MdeToggleCenteredLineCommand, + MdeCenteredLineKeeper, + ) + from .plugins.wiki_page import ( + MdeListBackLinksCommand, + MdeMakePageReferenceCommand, + MdeOpenHomePageCommand, + MdeOpenJournalCommand, + MdeOpenPageCommand, + MdePrepareFromTemplateCommand, + ) + + def plugin_loaded(): + load_logger() + on_after_install() + + def plugin_unloaded(): + unload_logger() + on_before_uninstall() diff --git a/plugins/__init__.py b/plugins/__init__.py new file mode 100644 index 00000000..e69de29b diff --git a/plugins/bootstrap.py b/plugins/bootstrap.py new file mode 100644 index 00000000..ea3746c5 --- /dev/null +++ b/plugins/bootstrap.py @@ -0,0 +1,82 @@ +import sys + +import sublime + +from .color_schemes import clear_color_schemes, select_color_scheme + +package_name = "MarkdownEditing" + + +def get_ingored_packages(): + settings = sublime.load_settings("Preferences.sublime-settings") + return settings.get("ignored_packages", []) + + +def save_ingored_packages(ignored_packages): + settings = sublime.load_settings("Preferences.sublime-settings") + settings.set("ignored_packages", ignored_packages) + sublime.save_settings("Preferences.sublime-settings") + + +def disable_native_markdown_package(): + ignored_packages = get_ingored_packages() + if "Markdown" not in ignored_packages: + reassign_syntax( + "Packages/Markdown/Markdown.sublime-syntax", + "Packages/MarkdownEditing/syntaxes/Markdown.sublime-syntax", + ) + reassign_syntax( + "Packages/Markdown/MultiMarkdown.sublime-syntax", + "Packages/MarkdownEditing/syntaxes/MultiMarkdown.sublime-syntax", + ) + ignored_packages.append("Markdown") + save_ingored_packages(ignored_packages) + + +def enable_native_markdown_package(): + ignored_packages = get_ingored_packages() + if "Markdown" in ignored_packages: + ignored_packages.remove("Markdown") + save_ingored_packages(ignored_packages) + + def reassign(): + reassign_syntax( + "Packages/MarkdownEditing/syntaxes/Markdown.sublime-syntax", + "Packages/Markdown/Markdown.sublime-syntax", + ) + reassign_syntax( + "Packages/MarkdownEditing/syntaxes/MultiMarkdown.sublime-syntax", + "Packages/Markdown/MultiMarkdown.sublime-syntax", + ) + + sublime.set_timeout(reassign, 100) + + +def reassign_syntax(current_syntax, new_syntax): + for window in sublime.windows(): + for view in window.views(): + syntax = view.settings().get("syntax") + if syntax and syntax == current_syntax: + view.assign_syntax(new_syntax) + + +def on_after_install(): + if "package_control" in sys.modules: + from package_control import events + + if events.install(package_name): + # Native package causes some conflicts. + disable_native_markdown_package() + # Prompts to select a color scheme. + select_color_scheme() + + +def on_before_uninstall(): + if "package_control" in sys.modules: + from package_control import events + + if events.remove(package_name): + # Native package causes some conflicts. + enable_native_markdown_package() + # Remove syntax specific color schemes. + clear_color_schemes() diff --git a/plugins/color_schemes.py b/plugins/color_schemes.py new file mode 100644 index 00000000..3e6a9e81 --- /dev/null +++ b/plugins/color_schemes.py @@ -0,0 +1,97 @@ +import re + +import sublime + +from .view import MdeTextCommand, syntax_specific_settings_file + + +class MdeSelectColorSchemeCommand(MdeTextCommand): + def run(self, edit): + select_color_scheme(self.view) + + +def select_color_scheme(view=None): + syntax_settings = syntax_specific_settings_file(view) or "Markdown.sublime-settings" + + window = view.window() if isinstance(view, sublime.View) else sublime.active_window() + pre_view = window.new_file( + flags=sublime.TRANSIENT, syntax="Packages/MarkdownEditing/syntaxes/Markdown.sublime-syntax" + ) + pre_view.set_scratch(True) + pre_view.run_command( + "append", + { + "characters": sublime.load_resource( + "Packages/MarkdownEditing/schemes/Preview.md" + ).replace("\r\n", "\n") + }, + ) + pre_view.set_read_only(True) + + md_settings = sublime.load_settings(syntax_settings) + md_scheme = md_settings.get("color_scheme") + + global_settings = sublime.load_settings("Preferences.sublime-settings") + global_scheme = global_settings.get("color_scheme") + schemes = [global_scheme, "MarkdownEditor.sublime-color-scheme"] + for scheme in sublime.find_resources("MarkdownEditor*.sublime-color-scheme"): + file_name = scheme.split("/")[-1] + if file_name not in schemes: + schemes.append(file_name) + + schemes_display = [] + selected_index = 0 + for i, s in enumerate(schemes): + m = re.search(r"[^/]+(?=\.(sublime-color-scheme|tmTheme)$)", s) + theme_display = m.group(0) + if s == global_scheme: + theme_display += " (Global)" + if not md_scheme: + theme_display += " (Current)" + selected_index = i + if s == md_scheme: + theme_display += " (Current)" + selected_index = i + schemes_display.append(theme_display) + + def set_scheme(scheme): + if scheme: + md_settings.set("color_scheme", scheme) + else: + md_settings.erase("color_scheme") + + def on_done(index): + if index == -1: + # restore previous color scheme + set_scheme(md_scheme) + elif index == 0: + # use global color scheme + set_scheme(None) + else: + # use markdown color scheme + set_scheme(schemes[index]) + sublime.save_settings(syntax_settings) + pre_view.close() + + def on_highlighted(index): + pre_view.settings().set("color_scheme", schemes[index]) + + window.show_quick_panel( + schemes_display, + flags=sublime.KEEP_OPEN_ON_FOCUS_LOST, + selected_index=selected_index, + on_select=on_done, + on_highlight=on_highlighted, + ) + + +def clear_color_schemes(): + clear_color_scheme("Markdown.sublime-settings") + clear_color_scheme("Markdown GFM.sublime-settings") + clear_color_scheme("MultiMarkdown.sublime-settings") + + +def clear_color_scheme(filename): + settings = sublime.load_settings(filename) + settings.erase("color_scheme") + sublime.save_settings(filename) diff --git a/plugins/folding.py b/plugins/folding.py new file mode 100644 index 00000000..f5440d9d --- /dev/null +++ b/plugins/folding.py @@ -0,0 +1,430 @@ +import sublime + +from .headings import all_headings +from .view import MdeTextCommand, MdeViewEventListener + +ST4 = int(sublime.version()) > 4000 + + +def folding_target_level(view): + return view.settings().get("mde.folding.target_level", -1) + + +def folded_region(view, region): + """ + Find first unfolded selection. + + :param view: The view + """ + for i in view.folded_regions(): + if i.contains(region): + return i + return None + + +def first_unfolded_selection(view): + """ + Find first unfolded selection. + + :param view: The view + """ + folded_regions = view.folded_regions() + for sel in view.sel(): + if not any(r.contains(sel) for r in folded_regions): + return sel + return sublime.Region(0, 0) + + +def show_first_unfolded_selection(view): + """ + Scroll to the first unfolded selection. + + :param view: The view + """ + if ST4: + view.show(first_unfolded_selection(view), keep_to_left=True, animate=False) + else: + view.show(first_unfolded_selection(view)) + + +def section_level(view, pt): + """ + Calculate heading level of the section `pt` is in. + + :param view: The view + :param region: The text position to find the section's region for + + :returns: The section level + """ + last_level = 0 + for heading_begin, heading_end, level in all_headings(view): + if heading_end < pt: + last_level = level + elif heading_begin < pt: + return level + else: + return last_level + + +def section_region_and_level(view, pt, target_level): + """ + Calculate `region` and heading level of the section `pt` is in. + + :param view: The view + :param region: The text position to find the section's region for + :param target_level: The level a section must have to be folded + + :returns: + region of the whole section including all its child sections, if `target_level` < 9 + region between previous and next heading, if `target_level` is 9 + """ + section_start = -1 + section_end = view.size() + section_level = 0 + for heading_begin, heading_end, heading_level in all_headings(view): + if heading_begin <= pt: + section_start = heading_end + section_level = heading_level + elif (section_level >= heading_level) or (target_level == 0 and section_start > 0): + section_end = heading_begin - 1 + break + if section_start >= 0 and section_end > section_start: + return (sublime.Region(section_start, section_end), section_level) + return (None, -1) + + +def sections_to_fold(view, region, target_level): + """ + Generate foldable sections of a given region by target_level. + + :param view: The view + :param region: The region to look for sections in + :param target_level: The level a section must have to be folded + + :yields: The regions to fold + + :returns: None + """ + section_start = -1 + section_end = region.end() + + for heading_begin, heading_end, heading_level in all_headings( + view, region.begin(), region.end() + ): + if target_level == 0 or heading_level <= target_level and section_start > 0: + section_end = heading_begin - 1 + yield sublime.Region(section_start, section_end) + section_start = -1 + if target_level == 0 or heading_level == target_level: + section_start = heading_end + + if section_start >= 0: + yield sublime.Region(section_start, region.end()) + + +def url_regions(view): + """ + Returns a list of all url regions specified by `"mde.auto_fold_link.selector"`. + + It caches the current view's regions to reduce api calls. Regions are fetched from API + whenever the function is called for another view or its content changed. It is just to prevent + API calls everytime caret is moved around. + + :param view: The view + + :returns: A list of regions + """ + view_id = view.id() + change_count = view.change_count() + + try: + if url_regions.view_id == view_id and url_regions.change_count == change_count: + return url_regions.regions + except AttributeError: + pass + + url_regions.view_id = view_id + url_regions.change_count = change_count + url_regions.regions = view.find_by_selector( + view.settings().get("mde.auto_fold_link.selector", "") + ) + return url_regions.regions + + +def urls_to_fold(view): + """ + Returns a list of url regions to fold. + + Returns all url regions but those a caret is placed within or which are partly selected. + + :param view: The view + :param region: The region urls to return for. + + :returns: A list of regions + """ + if not view.settings().get("mde.auto_fold_link.enabled", True): + return [] + + return [url for url in url_regions(view) if not any(url.contains(sel) for sel in view.sel())] + + +def fold_urls(view): + """ + Fold all urls the caret is not located within and unfold those it is. + + Partly or fully selected link urls are unfolded. + Urls contained by larger selections are folded or keep folded. + + :param view: The view + """ + fold_regions = [] + unfold_regions = [] + for url in url_regions(view): + if any(url.contains(sel) for sel in view.sel()): + unfold_regions.append(url) + else: + fold_regions.append(url) + + view.fold(fold_regions) + view.unfold(unfold_regions) + + +def unfold_urls(view): + """ + Unold all urls which are not part of a larger folded region (section). + + Make sure not to unfold sections, just because a contained link url is to be unfolded. + + :param view: The view + """ + folded_regions = view.folded_regions() + unfold_regions = [ + url for url in url_regions(view) if any(url.contains(folded) for folded in folded_regions) + ] + view.unfold(unfold_regions) + + +class MdeFoldSectionCommand(MdeTextCommand): + """ + This class describes a `mde_fold_section` command. + + The command folds or unfolds sections at least one caret is within. + + It's behavior depends on former call of `mde_fold_all_secitons` command and + the active `mde.folding.target_level` setting respectively. + + -1: The whole section, including all child sections is folded and unfolded. + The folded region begins after the nearest heading found before a caret's + position and ends with the next heading of same level after the caret. + 0: The region between two the headings enclosing the caret's position + is folded or unfolded. That's the so called outline mode. + >0: Like (-1) but all child sections of higher level then `target_level` + keep folded if their parent section is unfolded. + """ + + def description(self): + return "Toggle fold/unfold on current section" + + def run(self, edit): + view = self.view + target_level = folding_target_level(view) + sections = [] + levels = [] + unfold = False + for sel in view.sel(): + if any(s.contains(sel) for s in sections): + continue + section, level = section_region_and_level(view, sel.begin(), target_level) + if not section: + continue + folded_section = folded_region(view, section) + if folded_section: + if folded_section != section: + level = section_level(view, folded_section.begin()) + sections.append(folded_section) + unfold = True + else: + sections.append(section) + levels.append(level) + + if unfold: + regions_to_fold = [] + if target_level > -1: + # keep all child sections folded + for section, level in zip(sections, levels): + regions_to_fold.extend( + sections_to_fold(view, section, max(target_level, level + 1)) + ) + else: + for section in sections: + regions_to_fold.extend(sections_to_fold(view, section, -1)) + + view.unfold(sections) + view.fold(regions_to_fold + urls_to_fold(view)) + + else: + view.fold(sections) + + sublime.status_message( + "{} region{} {}folded".format( + len(sections), "s" if len(sections) > 1 else "", "un" if unfold else "" + ) + ) + + +class MdeFoldSectionContextCommand(MdeFoldSectionCommand): + """ + This class describes a `mde_fold_section_context` command. + """ + + def is_visible(self): + if not super().is_visible(): + return False + view = self.view + target_level = folding_target_level(view) + hasSection = False + for sel in view.sel(): + section, _ = section_region_and_level(view, sel.a, target_level) + if section: + folded = folded_region(view, section) + if folded: + return False + else: + hasSection = True + return hasSection + + +class MdeUnfoldSectionContextCommand(MdeFoldSectionCommand): + """ + This class describes a `mde_unfold_section_context` command. + """ + + def is_visible(self): + if not super().is_visible(): + return False + view = self.view + target_level = folding_target_level(view) + hasSection = False + for sel in view.sel(): + section, _ = section_region_and_level(view, sel.a, target_level) + if section: + folded = folded_region(view, section) + if folded: + hasSection = True + else: + return False + return hasSection + + +class MdeShowFoldAllSectionsCommand(MdeTextCommand): + """ + This class describes a `mde_show_fold_all_sections` command. + """ + + def run(self, edit): + view = self.view + view.window().run_command( + "show_overlay", {"overlay": "command_palette", "text": "MarkdownEditing: Fold"} + ) + + +class MdeFoldAllSectionsCommand(MdeTextCommand): + """ + This class describes a `mde_fold_all_sections` command which folds sections by level. + + With `target_level` + + - `= 0`, all sections are folded, but their headings keep visible. + - `> 0`, only headings of same or higher level are visible. + """ + + def run(self, edit, target_level=0): + view = self.view + view_region = sublime.Region(0, view.size()) + view.unfold(view_region) + sections = list(sections_to_fold(view, view_region, target_level)) + view.fold(sections + urls_to_fold(view)) + view.settings().set("mde.folding.target_level", target_level) + show_first_unfolded_selection(view) + sublime.status_message( + "{} region{} folded".format(len(sections), "s" if len(sections) > 1 else "") + ) + + +class MdeUnfoldAllSectionsCommand(MdeTextCommand): + """ + This class describes a `mde_unfold_all_sections` command which unfolds all sections. + """ + + def run(self, edit): + view = self.view + view.settings().erase("mde.folding.target_level") + view.unfold(sublime.Region(0, view.size())) + if view.settings().get("mde.auto_fold_link.enabled", True): + fold_urls(view) + show_first_unfolded_selection(view) + sublime.status_message("all regions unfolded") + + +class MdeFoldLinksCommand(MdeTextCommand): + """ + This class describes a `mde_fold_links` command. + + It can be used to eigther toggle automatic link folding or set it on/off for called view. + + Example: + + ```json + { "command": "mde_fold_links", "args": {"fold": true} } + ``` + """ + + def is_checked(self): + return self.view.settings().get("mde.auto_fold_link.enabled", True) + + def run(self, edit, fold=None): + if fold is None: + fold = not self.is_checked() + + self.view.settings().set("mde.auto_fold_link.enabled", fold) + + if fold: + fold_urls(self.view) + else: + unfold_urls(self.view) + + +class MdeFoldLinksListener(MdeViewEventListener): + """ + This class describes an automatic link folding event listener. + """ + + @classmethod + def is_applicable(cls, settings): + return MdeViewEventListener.is_applicable(settings) and settings.get( + "mde.auto_fold_link.enabled", True + ) + + def on_init(self): + """ + Fold all links after application startup. + """ + fold_urls(self.view) + + def on_load(self): + """ + Fold all links once file is loaded. + """ + fold_urls(self.view) + + def on_activated(self): + """ + Update link folding when activating view. + """ + fold_urls(self.view) + + def on_selection_modified(self): + """ + Update link folding when moving caret around. + """ + fold_urls(self.view) diff --git a/footnotes.py b/plugins/footnotes.py similarity index 57% rename from footnotes.py rename to plugins/footnotes.py index 2a349080..35d7a89e 100644 --- a/footnotes.py +++ b/plugins/footnotes.py @@ -1,15 +1,13 @@ -import sublime -import sublime_plugin import re -try: - from MarkdownEditing.mdeutils import * -except ImportError: - from mdeutils import * -DEFINITION_KEY = 'MarkdownEditing-footnote-definitions' -REFERENCE_KEY = 'MarkdownEditing-footnote-references' -REFERENCE_REGEX = "\[\^([^\]]*)\]" -DEFINITION_REGEX = "^ *\[\^([^\]]*)\]:" +import sublime + +from .view import MdeTextCommand, MdeViewEventListener + +DEFINITION_KEY = "MarkdownEditing-footnote-definitions" +REFERENCE_KEY = "MarkdownEditing-footnote-references" +DEFINITION_REGEX = r"^[\t ]*\[\^([^\]]*)\]:" +REFERENCE_REGEX = r"\[\^([^\]]*)\]" def get_footnote_references(view): @@ -64,61 +62,73 @@ def is_footnote_reference(view): def strip_trailing_whitespace(view, edit): - tws = view.find('\s+\Z', 0) + tws = view.find(r"\s+\Z", 0) if tws: view.erase(edit, tws) -class MarkFootnotes(sublime_plugin.EventListener): +class MdeMarkFootnotesListener(MdeViewEventListener): + def update_footnote_data(self): + self.view.add_regions( + REFERENCE_KEY, self.view.find_all(REFERENCE_REGEX), "", "cross", sublime.HIDDEN + ) + self.view.add_regions( + DEFINITION_KEY, self.view.find_all(DEFINITION_REGEX), "", "cross", sublime.HIDDEN + ) - def update_footnote_data(self, view): - if view_is_markdown(view): - view.add_regions(REFERENCE_KEY, view.find_all(REFERENCE_REGEX), '', 'cross', sublime.HIDDEN) - view.add_regions(DEFINITION_KEY, view.find_all(DEFINITION_REGEX), '', 'cross', sublime.HIDDEN) + def on_load(self): + self.update_footnote_data() - def on_modified_async(self, view): - self.update_footnote_data(view) + def on_modified_async(self): + self.update_footnote_data() - def on_load(self, view): - self.update_footnote_data(view) - - -class GatherMissingFootnotesCommand(MDETextCommand): +class MdeGatherMissingFootnotesCommand(MdeTextCommand): def run(self, edit): refs = get_footnote_identifiers(self.view) defs = get_footnote_definition_markers(self.view) - missingnotes = [note_token for note_token in refs if not note_token in defs] + missingnotes = [note_token for note_token in refs if note_token not in defs] if len(missingnotes): self.view.insert(edit, self.view.size(), "\n") for note in missingnotes: - self.view.insert(edit, self.view.size(), '\n [^%s]: ' % note) - + self.view.insert(edit, self.view.size(), "\n [^%s]: " % note) -class InsertFootnoteCommand(MDETextCommand): +class MdeInsertFootnoteCommand(MdeTextCommand): def run(self, edit): view = self.view markernum = get_next_footnote_marker(view) - markernum_str = '[^%s]' % markernum + markernum_str = "[^%s]" % markernum for sel in view.sel(): startloc = sel.end() if bool(view.size()): - targetloc = view.find('(\s|$)', startloc).begin() + targetloc = view.find(r"(\s|$)", startloc).begin() else: targetloc = 0 view.insert(edit, targetloc, markernum_str) if len(view.sel()) > 0: - view.insert(edit, view.size(), '\n' + markernum_str + ': ') + view.insert(edit, view.size(), "\n" + markernum_str + ": ") view.sel().clear() view.sel().add(sublime.Region(view.size(), view.size())) - view.run_command('set_motion', {"inclusive": True, "motion": "move_to", "motion_args": {"extend": True, "to": "eof"}}) - if view.settings().get('command_mode'): - view.run_command('enter_insert_mode', {"insert_command": "move", "insert_args": {"by": "characters", "forward": True}}) - - -class GoToFootnoteDefinitionCommand(MDETextCommand): - + view.run_command( + "set_motion", + { + "inclusive": True, + "motion": "move_to", + "motion_args": {"extend": True, "to": "eof"}, + }, + ) + if view.settings().get("command_mode"): + view.run_command( + "enter_insert_mode", + { + "insert_command": "move", + "insert_args": {"by": "characters", "forward": True}, + }, + ) + + +class MdeGotoFootnoteDefinitionCommand(MdeTextCommand): def run(self, edit): defs = get_footnote_definition_markers(self.view) regions = self.view.get_regions(REFERENCE_KEY) @@ -134,7 +144,7 @@ def run(self, edit): if not target: try: target = self.view.substr(self.view.find(REFERENCE_REGEX, sel[-1].end()))[2:-1] - except: + except Exception: pass if target: self.view.sel().clear() @@ -142,40 +152,36 @@ def run(self, edit): self.view.show(defs[target]) -class GoToFootnoteReferenceCommand(MDETextCommand): - +class MdeGotoFootnoteReferenceCommand(MdeTextCommand): def run(self, edit): refs = get_footnote_references(self.view) match = is_footnote_definition(self.view) if match: target = match.groups()[0] self.view.sel().clear() - [self.view.sel().add(a) for a in refs[target]] + self.view.sel().add_all(refs[target]) self.view.show(refs[target][0]) -class MagicFootnotesCommand(MDETextCommand): - +class MdeMagicFootnotesCommand(MdeTextCommand): def run(self, edit): - if (is_footnote_definition(self.view)): - self.view.run_command('go_to_footnote_reference') - elif (is_footnote_reference(self.view)): - self.view.run_command('go_to_footnote_definition') + if is_footnote_definition(self.view): + self.view.run_command("mde_goto_footnote_reference") + elif is_footnote_reference(self.view): + self.view.run_command("mde_goto_footnote_definition") else: - self.view.run_command('insert_footnote') - + self.view.run_command("mde_insert_footnote") -class SwitchToFromFootnoteCommand(MDETextCommand): +class MdeSwitchToFromFootnoteCommand(MdeTextCommand): def run(self, edit): - if (is_footnote_definition(self.view)): - self.view.run_command('go_to_footnote_reference') + if is_footnote_definition(self.view): + self.view.run_command("mde_goto_footnote_reference") else: - self.view.run_command('go_to_footnote_definition') - + self.view.run_command("mde_goto_footnote_definition") -class SortFootnotesCommand(MDETextCommand): +class MdeSortFootnotesCommand(MdeTextCommand): def run(self, edit): strip_trailing_whitespace(self.view, edit) defs = get_footnote_definition_markers(self.view) @@ -183,16 +189,19 @@ def run(self, edit): erase = [] keyorder = map(lambda x: self.view.substr(x)[2:-1], self.view.get_regions(REFERENCE_KEY)) keys = [] - [keys.append(r) for r in keyorder if not r in keys] + for r in keyorder: + if r not in keys: + keys.append(r) for (key, item) in defs.items(): - fnend = self.view.find('(\s*\Z|\n\s*\n(?!\ {4,}))', item.end()) + fnend = self.view.find(r"(\s*\Z|\n\s*\n(?!\ {4,}))", item.end()) fnreg = sublime.Region(item.begin(), fnend.end()) notes[key] = self.view.substr(fnreg).strip() erase.append(fnreg) erase.sort() erase.reverse() - [self.view.erase(edit, reg) for reg in erase] + for reg in erase: + self.view.erase(edit, reg) for key in keys: - self.view.insert(edit, self.view.size(), '\n\n ' + notes[key]) + self.view.insert(edit, self.view.size(), "\n\n " + notes[key]) diff --git a/plugins/headings/__init__.py b/plugins/headings/__init__.py new file mode 100644 index 00000000..5101e049 --- /dev/null +++ b/plugins/headings/__init__.py @@ -0,0 +1,5 @@ +from .common import * +from .goto import * +from .level import * +from .style import * +from .underlined import * diff --git a/plugins/headings/common.py b/plugins/headings/common.py new file mode 100644 index 00000000..07a075fd --- /dev/null +++ b/plugins/headings/common.py @@ -0,0 +1,66 @@ +import re +import sublime + +from ..view import MdeViewEventListener + +HEADINGS_RE = re.compile( + r""" + ^( [ \t]* ) # leading whitespace + (?: + ( \#{1,6} ) [ \t]+ ( [^\n]+ ) # ATX headings + | ( [^-=#\s][^|\n]* ) \n \1 ( -{3,} | ={3,} ) # SETEXT headings + ) [ \t]*$ # maybe trailing whitespace + """, + re.X | re.M, +) + + +def all_headings(view, start=0, end=None): + if end is None: + end = view.size() + text = view.substr(sublime.Region(start, end)) + for m in HEADINGS_RE.finditer(text): + title_begin = start + m.start() + title_end = start + m.end() + if m.group(2): + # ATX headings use group 2 (heading) and 3 (leading hashes) + level = m.end(2) - m.start(2) + else: + # SETEXT headings use group 4 (text) and 5 (underlines) + level = 2 if text[m.start(5)] == "-" else 1 + # ignore front matter and raw code blocks + if view.match_selector(title_begin, "- markup.raw"): + yield (title_begin, title_end, level) + return None + + +def first_heading_text(view): + text = view.substr(sublime.Region(0, min(view.size(), 1024 * 1024))) + for m in HEADINGS_RE.finditer(text): + if m.group(3): + title_begin = m.start(3) + title_end = m.end(3) + else: + title_begin = m.start(4) + title_end = m.end(4) + # ignore front matter and raw code blocks + if view.match_selector(title_begin, "- markup.raw"): + return text[title_begin:title_end] + return text[0 : text.find("\n")] + + +class MdeUnsavedViewNameSetter(MdeViewEventListener): + """ + This view event listener prints the first heading as tab title of unsaved documents. + """ + + MAX_NAME = 50 + + def on_modified(self): + if self.view.file_name() is not None: + return + + name = first_heading_text(self.view) + if len(name) > self.MAX_NAME: + name = name[: self.MAX_NAME] + "…" + self.view.set_name(name) diff --git a/plugins/headings/goto.py b/plugins/headings/goto.py new file mode 100644 index 00000000..80d8287e --- /dev/null +++ b/plugins/headings/goto.py @@ -0,0 +1,67 @@ +import sublime + +from .common import all_headings +from ..view import MdeTextCommand + + +class MdeGotoNextHeadingCommand(MdeTextCommand): + def run(self, edit, same_level=True): + view = self.view + headings = tuple(all_headings(view)) + new_sel = [] + for sel in view.sel(): + section_level = 0 + for title_begin, title_end, level in headings: + if title_begin <= sel.begin(): + section_level = level + elif not same_level or section_level >= level: + new_sel.append(sublime.Region(title_begin, title_end)) + break + + if not new_sel: + sublime.status_message("No heading can be found") + return + + view.sel().clear() + view.sel().add_all(new_sel) + view.show(new_sel[-1]) + + +class MdeGotoPreviousHeadingCommand(MdeTextCommand): + def run(self, edit, same_level=True): + view = self.view + headings = tuple(all_headings(view)) + new_sel = [] + max_level = 0 + last_level = 0 + found = False + for sel in view.sel(): + prev = {} + for title_begin, title_end, level in headings: + max_level = max(max_level, level) + if title_end < sel.begin(): + for lvl in range(level, max_level + 1): + prev[lvl] = (title_begin, title_end) + last_level = level + else: + found = True + break + if found: + if same_level: + while level not in prev and level > 0: + level -= 1 + if level > 0 and level in prev: + new_sel.append(sublime.Region(prev[level][0], prev[level][1])) + else: + if last_level > 0 and last_level in prev: + new_sel.append(sublime.Region(prev[last_level][0], prev[last_level][1])) + elif max_level > 0: + new_sel.append(sublime.Region(title_begin, title_end)) + + if not new_sel: + sublime.status_message("No heading can be found") + return + + view.sel().clear() + view.sel().add_all(new_sel) + view.show(new_sel[-1]) diff --git a/plugins/headings/level.py b/plugins/headings/level.py new file mode 100644 index 00000000..627999c2 --- /dev/null +++ b/plugins/headings/level.py @@ -0,0 +1,122 @@ +import re + +from ..logging import logger +from ..view import MdeTextCommand + + +class MdeChangeHeadingsLevelCommand(MdeTextCommand): + """ + The `mde_change_headings_level` command modifies headings levels to an + absolute or by a relative value. + + 1. Carets are moved to the beginning of each header label. + 2. Indentation level is kept intact. + 3. Works within block quotes. + 4. Respects `mde.match_heading_hashes` setting. + + Absolute: + + ```json + { "command": "mde_change_headings_level", "args": {"to": 2, "select": false} } + ``` + + Relative + + ```json + { "command": "mde_change_headings_level", "args": {"by": -1, "select": false} } + ``` + """ + + MAX_LEVEL = 6 + + def description(self): + # Used as the name for Undo. + return "Change Headings Level" + + def run(self, edit, to=None, by=None, select=False): + """ + Execute `mde_change_headings_level` + + :param edit: The edit token + :type edit: sublime.Edit + :param to: target heading level + :type to: int + :param by: increment to change heading level by + :type by: int + :param select: whether to select heading text or not + :type select: bool + """ + if by is not None: + try: + by = int(by) + except (TypeError, ValueError): + logger.error("Invalid headings level step size specified!") + return + + def calc_level(start): + return (int(start.count("#") + by)) % self.MAX_LEVEL + + self._set_level(edit, calc_level, select) + + elif to is not None: + try: + to = max(0, min(self.MAX_LEVEL, int(to))) + except (TypeError, ValueError): + logger.error("Invalid headings level specified!") + return + + def calc_level(start): + return to + + self._set_level(edit, calc_level, select) + + else: + logger.error("No headings level specified!") + + def _set_level(self, edit, calc_level, select): + view = self.view + vsels = view.sel() + match_heading_hashes = view.settings().get("mde.match_heading_hashes") + pattern = re.compile(r"^([ \t>]*)(?:(\#{1,6})[ \t]+?|(?![-+*#]))(.*?)(?:[ \t]+\#+)?[ \t]*$") + + # One or more selections may span multiple lines each of them to change heading level for. + # To correctly handle caret placements split all selections into single lines first. + regions = [region for sel in vsels for region in view.split_by_newlines(sel)] + vsels.clear() + vsels.add_all(regions) + regions = [] + + for sel in vsels: + line = view.line(sel) + string = view.substr(line) + match = pattern.match(string) + if not match: + logger.debug( + "Change heading level ignored line %d: '%s'", + view.rowcol(line.a)[0] + 1, + string, + ) + continue + + quote, hashes, text = match.groups() + to = calc_level(hashes or "") + new_text = quote + "#" * to + " " * bool(to) + text + if match_heading_hashes and to > 0: + new_text += " " + "#" * to + view.replace(edit, line, new_text) + if select: + line.a += len(quote) + bool(to) + to + line.b = line.a + len(text) * bool(select) + else: + line = view.line(line.a) + if hashes: + line.a = min(line.b, max(line.a, sel.a + to - len(hashes) - int(not to))) + else: + line.a = min(line.b, max(line.a, sel.a + to + bool(to))) + line.b = line.a + regions.append(line) + + # fix caret positions and selections + if regions: + vsels.clear() + vsels.add_all(regions) diff --git a/plugins/headings/style.py b/plugins/headings/style.py new file mode 100644 index 00000000..b05b40d0 --- /dev/null +++ b/plugins/headings/style.py @@ -0,0 +1,94 @@ +import os.path +import re + +from ..view import MdeTextCommand, MdeViewEventListener + + +class MdeMatchHeadingHashesCommand(MdeTextCommand): + """ + The `mde_match_heading_hashes` command adds or removes trailing hashes to or from atx headings. + + If no argument is passed, trailing hashes are added or removed depending on actual value of + the current view's `mde.match_heading_hashes` setting. + + If the argument `enabled` is of `True` or `False`, its value is applied to view specific + `mde.match_heading_hashes` setting and trailing hashes are added and removed accordingly. + + Note: The function balances the amount of leading and trailing hashes. + """ + + def run(self, edit, enabled=None): + view = self.view + + if enabled is None: + enabled = view.settings().get("mde.match_heading_hashes", False) + elif isinstance(enabled, bool): + view.settings().set("mde.match_heading_hashes", enabled) + else: + raise TypeError("Argument: 'enabled' must be a bool!") + + if enabled: + replacement = r"\1\2 \3 \2" + else: + replacement = r"\1\2 \3" + + pattern = re.compile(r"^([ \t]*)(#{1,6})[ \t]+(.*?)(?:[ \t]+#+)?[ \t]*$") + for region in reversed(view.find_by_selector("markup.heading")): + text = view.substr(region) + new_text = pattern.sub(replacement, text) + if text != new_text: + view.replace(edit, region, new_text) + + +class MdeMatchHeadingHashesDetector(MdeViewEventListener): + """ + The `MdeMatchHeadingHashesDetector` auto-detects ATX heading style. + + The detected style is applied to the view specific setting `"mde.match_heading_hashes"` + so that any modification to headings works as expected. + """ + + @classmethod + def is_applicable(cls, settings): + try: + if "Markdown" not in settings.get("syntax"): + return False + if not settings.get("mde.detect_heading_style", False): + # remove view specific setting to use global value from preferences + settings.erase("mde.match_heading_hashes") + return False + return True + except (AttributeError, TypeError): + return False + + def on_load(self): + self.auto_detect_heading_style() + + def on_pre_save(self): + self.auto_detect_heading_style() + + def auto_detect_heading_style(self): + view = self.view + + # don't break syntax_test files + file_name = view.file_name() + if file_name and os.path.basename(file_name).startswith("syntax_test"): + view.settings().set("mde.auto_match_heading_hashes", False) + return + + num_leading = 0 + num_trailing = 0 + + for h1, h2 in zip( + view.find_by_selector("markup.heading")[:10], + view.find_by_selector("markup.heading - punctuation.definition.heading")[:10], + ): + num_leading += 1 + if h1.end() > h2.end(): + num_trailing += 1 + + if num_leading: + view.settings().set("mde.match_heading_hashes", num_trailing / num_leading > 0.5) + + if view.settings().get("mde.auto_match_heading_hashes", False): + view.run_command("mde_match_heading_hashes") diff --git a/underlined_headers.py b/plugins/headings/underlined.py similarity index 58% rename from underlined_headers.py rename to plugins/headings/underlined.py index c309900a..671cad64 100644 --- a/underlined_headers.py +++ b/plugins/headings/underlined.py @@ -1,47 +1,34 @@ -"""Commands for working with with setext-style (underlined) Markdown headers. - -Header dashes can be completed with . For example: - - This is an H2 - - - -Becomes: - - This is an H2 - ------------- - -Inspired by the similar TextMate command. - -Also adds "Fix Underlined Markdown Headers" to Tools > Command Palette. After modifying -header text, this command will re-align the underline dashes with the new text length. - -""" -import sublime -import sublime_plugin -import re import itertools -try: - from MarkdownEditing.mdeutils import * -except ImportError: - from mdeutils import * +import re +import sublime + +from ..view import MdeTextCommand -SETEXT_DASHES_RE = re.compile( r''' +SETEXT_DASHES_RE = re.compile( + r""" (?: =+ | -+ ) # A run of ---- or ==== underline characters. \s* # Optional trailing whitespace. $ # Must fill the while line. Don't match "- list items" - ''', re.X ) + """, + re.X, +) -SETEXT_HEADER_RE = re.compile( r''' +SETEXT_HEADER_RE = re.compile( + r""" ^(.+)\n ( =+ | -+ ) # A run of ---- or ==== underline characters. [ \t]* # Optional trailing whitespace. $ # Must fill the while line. Don't match "- list items" - ''', re.X | re.M ) + """, + re.X | re.M, +) def fix_dashes(view, edit, text_region, dash_region): - """Replaces the underlined "dash" region of a setext header with a run of - dashes or equal-signs that match the length of the header text.""" + """ + Replaces the underlined "dash" region of a setext header with a run of + dashes or equal-signs that match the length of the header text. + """ if len(view.substr(text_region).strip()) == 0: # Ignore dashes not under text. They are HRs. @@ -53,11 +40,31 @@ def fix_dashes(view, edit, text_region, dash_region): view.replace(edit, dash_region, new_dashes) -class CompleteUnderlinedHeaderCommand(MDETextCommand): +class MdeCompleteUnderlinedHeadingsCommand(MdeTextCommand): + """ + The `mde_complete_underline_headings` command inserts enough dash characters + to match the length of the previous (header text) line, if the selection + looks like a setext underline of - or = . - """If the current selection is looks like a setext underline of - or = , - then inserts enough dash characters to match the length of the previous - (header text) line.""" + Before: + + ```markdown + This is an H2 + -| + ``` + + After: + + ```markdown + This is an H2 + -------------| + ``` + + Note: + + If the line before a selection is empty or starts with single dash, a tab + character is inserted instead assuming the current line belonging to a list. + """ def run(self, edit): for region in self.view.sel(): @@ -70,33 +77,53 @@ def run(self, edit): if text_line.begin() < 0: continue - text = self.view.substr(text_line) - dashes = self.view.substr(dashes_line) - - # ignore, text_line is a list item - if text.lstrip().startswith("-") and len(dashes.strip()) < 2: - settings = self.view.settings() - use_spaces = bool(settings.get('translate_tabs_to_spaces')) - tab_size = int(settings.get('tab_size', 8)) - indent_characters = '\t' - if use_spaces: - indent_characters = ' ' * tab_size - self.view.insert(edit, dashes_line.begin(), indent_characters) - break - - m = SETEXT_DASHES_RE.match(dashes) - if m: + text = self.view.substr(text_line).lstrip() + dashes = self.view.substr(dashes_line).strip() + bullets = self.view.settings().get("mde.list_indent_bullets", ["*", "-", "+"]) + + # ignore, text_line is a list item or empty + if len(dashes) < 2 and (not text or text[0] in bullets): + self.view.insert(edit, region.begin(), "\t") + continue + + match = SETEXT_DASHES_RE.match(dashes) + if match: fix_dashes(self.view, edit, text_line, dashes_line) -class FixAllUnderlinedHeadersCommand(MDETextCommand): +class MdeConvertUnderlinedHeadingsToAtxCommand(MdeTextCommand): + """ + The `mde_convert_underlined_headings` command searches for all setext headings + and converts them to atx format. + """ + + def run(self, edit, closed=False): + regions = list(self.view.sel()) + if len(regions) == 1 and regions[0].size() == 0: + regions = [sublime.Region(0, self.view.size())] + regions.reverse() + for region in regions: + txt = self.view.substr(region) + matches = list(SETEXT_HEADER_RE.finditer(txt)) + matches.reverse() + for m in matches: + mreg = sublime.Region(region.begin() + m.start(), region.begin() + m.end()) + atx = "# " + if "-" in m.group(2): + atx = "#" + atx + closing = atx[::-1] if closed else "" + self.view.replace(edit, mreg, atx + m.group(1) + closing) + - """Searches for all setext headings resize them to match the preceding - header text.""" +class MdeFixUnderlinedHeadingsCommand(MdeTextCommand): + """ + The `mde_fix_underlined_headings` command searches for all setext headings + resize them to match the preceding header text. + """ def description(self): # Used as the name for Undo. - return 'Fix Underlined Markdown Headers' + return "Fix Underlined Markdown Headings" def run(self, edit): lines = self.view.split_by_newlines(sublime.Region(0, self.view.size())) @@ -118,23 +145,3 @@ def run(self, edit): m = SETEXT_DASHES_RE.match(dashes_text) if m: fix_dashes(self.view, edit, text_line, dashes_line) - - -class ConvertToAtxCommand(MDETextCommand): - - def run(self, edit, closed=False): - regions = list(self.view.sel()) - if len(regions) == 1 and regions[0].size() == 0: - regions = [sublime.Region(0, self.view.size())] - regions.reverse() - for region in regions: - txt = self.view.substr(region) - matches = list(SETEXT_HEADER_RE.finditer(txt)) - matches.reverse() - for m in matches: - mreg = sublime.Region(region.begin()+m.start(), region.begin()+m.end()) - atx = "# " - if '-' in m.group(2): - atx = "#" + atx - closing = atx[::-1] if closed else "" - self.view.replace(edit, mreg, atx + m.group(1) + closing) diff --git a/lint.py b/plugins/lint.py similarity index 52% rename from lint.py rename to plugins/lint.py index 0e041918..5d6a09ba 100644 --- a/lint.py +++ b/plugins/lint.py @@ -1,10 +1,135 @@ -import sublime -import sublime_plugin import re -try: - from MarkdownEditing.mdeutils import * -except ImportError: - from mdeutils import * +import sublime +import subprocess + +from .view import MdeTextCommand + + +class MdeMarkdownLintMdlCommand(MdeTextCommand): + def run(self, edit): + try: + is_windows = sublime.platform() == "windows" + + mdl_config = self.view.settings().get("mde.lint", {}).get("mdl", {}) + sublime.status_message("Linting file...") + text_content = self.view.substr(sublime.Region(0, self.view.size())) + text_content = text_content.encode("utf-8") + + executable_name = mdl_config.get("executable") + if not executable_name: + executable_name = "mdl.bat" if is_windows else "mdl" + + startupinfo = None + if is_windows: + startupinfo = subprocess.STARTUPINFO() + startupinfo.dwFlags |= subprocess.STARTF_USESHOWWINDOW + startupinfo.wShowWindow = subprocess.SW_HIDE + + # call mdl version + process = subprocess.Popen( + [executable_name] + mdl_config.get("additional_arguments", []), + bufsize=1024 * 1024 + len(text_content), + stdin=subprocess.PIPE, + stdout=subprocess.PIPE, + stderr=subprocess.PIPE, + startupinfo=startupinfo, + ) + stdout, stderr = process.communicate(text_content) + if stderr: + result = False + error = self.read_result(stderr) + outputtxt = error + else: + result = self.read_result(stdout) + outputtxt = result + sublime.status_message("MarkdownLint: %d error(s) found" % len(result.split("\n"))) + + window = self.view.window() or sublime.active_window() + if outputtxt: + output = window.create_output_panel("mde") + output.run_command("insert", {"characters": outputtxt}) + window.run_command("show_panel", {"panel": "output.mde"}) + else: + sublime.status_message("MarkdownLint: no errors found") + window.destroy_output_panel("mde") + + except OSError as e: + print(e) + sublime.error_message( + "It looks like markdownlint is not installed.\n" + "Please make sure that it is installed and globally accessible as `mdl`." + ) + except Exception as e: + print(e) + + def read_result(self, stdout): + r = str(stdout, encoding="utf-8") + return r.strip().replace("\r", "").replace("(stdin):", "") + + +class MdeMarkdownLintCommand(MdeTextCommand): + + blockdef = [] + frontmatter = "meta.frontmatter" + scope_block = "markup.raw.block.markdown" + + def run(self, edit): + mddef = globals()["mddef"] + text = self.view.substr(sublime.Region(0, self.view.size())) + st = self.view.settings().get("mde.lint", {}) + uselist = [] + disablelist = st["disable"] + for cl in mddef.__subclasses__(): + if cl.__name__ not in disablelist: + uselist.append(cl) + result = [] + for mddef in uselist: + r = self.test( + mddef(st[mddef.__name__] if mddef.__name__ in st else None, self.view), text + ) + result.extend(r) + window = self.view.window() or sublime.active_window() + if len(result) > 0: + sublime.status_message("MarkdownLint: %d error(s) found" % len(result)) + result = sorted(result, key=lambda t: t[0]) + outputtxt = "" + for t in result: + (row, col) = self.view.rowcol(t[0]) + outputtxt += "line %d: %s, %s\n" % (row + 1, t[1], t[2]) + output = window.create_output_panel("mde") + output.run_command("insert", {"characters": outputtxt}) + window.run_command("show_panel", {"panel": "output.mde"}) + else: + sublime.status_message("MarkdownLint: no errors found") + window.destroy_output_panel("mde") + + def test(self, tar, text): + loc = tar.locator + # print(tar) + # print(repr(loc)) + it = re.finditer(loc, text, tar.flag) + ret = [] + for mr in it: + # print('find %d,%d' % (mr.start(tar.gid), mr.end(tar.gid))) + if self.view.match_selector(mr.start(0), self.frontmatter): + continue + if self.view.match_selector(mr.start(0), self.scope_block): + if tar.__class__ not in self.blockdef: + continue + ans = tar.test(text, mr.start(tar.gid), mr.end(tar.gid)) + for p in ans: + ret.append((p, str(tar), ans[p])) + # (row, col) = self.view.rowcol(p) + # print('line %d: %s, %s' % (row + 1, tar, ans[p])) + + # if not ans: + # ret = False + # (row, col) = self.view.rowcol(mr.start(tar.gid)) + # print('line %d: %s ' % (row + 1, tar)) + if tar.finish: + break + + return ret class mddef(object): @@ -17,13 +142,13 @@ def __init__(self, settings, view): self.settings = settings def __str__(self): - return self.__class__.__name__.upper() + ' - ' + self.desc + return self.__class__.__name__.upper() + " - " + self.desc class md001(mddef): flag = re.M - desc = 'Header levels should only increment by one level at a time' - locator = r'^#{1,6}(?!#)' + desc = "Header levels should only increment by one level at a time" + locator = r"^#{1,6}(?!#)" lastMatch = None @@ -34,70 +159,69 @@ def test(self, text, s, e): n2 = e - s if n2 > n1: if n2 != n1 + 1: - ret[s] = 'expected %d, %d found' % (n1 + 1, n2) - self.lastMatch = text[s: e] + ret[s] = "expected %d, %d found" % (n1 + 1, n2) + self.lastMatch = text[s:e] return ret class md002(mddef): flag = re.M - desc = 'First header should be a h1 header' - locator = r'^(?:#{1,6}(?!#))|(?:-+$|=+$)' + desc = "First header should be a h1 header" + locator = r"^(?:#{1,6}(?!#))|(?:-+$|=+$)" def test(self, text, s, e): ret = {} # print (text[s:e]) self.finish = True - if re.match(r'#{1,6}(?!#)', text[s:e]): + if re.match(r"#{1,6}(?!#)", text[s:e]): if e - s != 1: - ret[s] = 'level %d found' % (e - s) - elif re.match('-+|=+', text[s:e]): - if not re.match('=+', text[s:e]): - ret[s] = 'level 2 found' + ret[s] = "level %d found" % (e - s) + elif re.match("-+|=+", text[s:e]): + if not re.match("=+", text[s:e]): + ret[s] = "level 2 found" return ret class md003(mddef): flag = re.M - desc = 'Header style' - locator = r'^((?:-+|=+)|(?:#{1,6}(?!#).*))$' + desc = "Header style" + locator = r"^((?:-+|=+)|(?:#{1,6}(?!#).*))$" gid = 1 - ratx = r'^(#{1,6}(?!#)).*$' - ratxc = r'^(#{1,6}(?!#)).*?(#+)$' - rsetext = r'[\-\=]+' + ratx = r"^(#{1,6}(?!#)).*$" + ratxc = r"^(#{1,6}(?!#)).*?(#+)$" + rsetext = r"[\-\=]+" def test(self, text, s, e): ret = {} t = text[s:e] - if self.settings == 'atx': - if not re.match(self.ratx, t) or\ - re.match(self.ratxc, t): - ret[s] = 'expected atx' - elif self.settings == 'atx_closed': + if self.settings == "atx": + if not re.match(self.ratx, t) or re.match(self.ratxc, t): + ret[s] = "expected atx" + elif self.settings == "atx_closed": if not re.match(self.ratxc, t): - ret[s] = 'expected atx_closed' - elif self.settings == 'setext': + ret[s] = "expected atx_closed" + elif self.settings == "setext": if not re.match(self.rsetext, t): - ret[s] = 'expected setext' - elif self.settings == 'any': + ret[s] = "expected setext" + elif self.settings == "any": if re.match(self.ratx, t): if re.match(self.ratxc, t): - self.settings = 'atx_closed' + self.settings = "atx_closed" else: - self.settings = 'atx' + self.settings = "atx" return self.test(text, s, e) elif re.match(self.rsetext, t): - self.settings = 'setext' + self.settings = "setext" return self.test(text, s, e) return ret class md004(mddef): flag = re.M - desc = 'Unordered list style' - locator = r'^([ ]{0,3})[*+-](?=\s)' - eol = r'^(?=\S)' + desc = "Unordered list style" + locator = r"^([ ]{0,3})[*+-](?=\s)" + eol = r"^(?=\S)" gid = 1 lastSym = None lastpos = -1 @@ -114,20 +238,20 @@ def test(self, text, s, e): ret = {} lvstack = [] basenspaces = e - s - sym = text[e:e + 1] + sym = text[e : e + 1] (ans, exp) = self.testsingle(sym) if ans is None: (ans, exp) = self.testcyc(sym, -1) if ans is False: - ret[e] = '%s expected, %s found' % (exp, sym) + ret[e] = "%s expected, %s found" % (exp, sym) elif ans is False: - ret[e] = '%s expected, %s found' % (exp, sym) + ret[e] = "%s expected, %s found" % (exp, sym) - rest = text[e + 1:] + rest = text[e + 1 :] mr = re.search(self.eol, rest, re.M) end = mr.start(0) if mr else len(rest) block = rest[:end] - mrs = re.finditer(r'^(\s*)([*\-+])\s+', block, re.M) + mrs = re.finditer(r"^(\s*)([*\-+])\s+", block, re.M) for mr in mrs: self.lastpos = e + 1 + mr.end(0) sym = mr.group(2) @@ -149,22 +273,20 @@ def test(self, text, s, e): lvstack.append(nspaces) (ans, exp) = self.testcyc(sym, lv) if ans is False: - ret[e + 1 + - mr.start(2)] = '%s expected, %s found' % (exp, sym) + ret[e + 1 + mr.start(2)] = "%s expected, %s found" % (exp, sym) else: if not ans: - ret[e + 1 + - mr.start(2)] = '%s expected, %s found' % (exp, sym) + ret[e + 1 + mr.start(2)] = "%s expected, %s found" % (exp, sym) return ret def testsingle(self, sym): - if self.settings == 'asterisk': - return (sym == '*', '*') - if self.settings == 'plus': - return (sym == '+', '+') - if self.settings == 'dash': - return (sym == '-', '-') - if self.settings == 'single': + if self.settings == "asterisk": + return (sym == "*", "*") + if self.settings == "plus": + return (sym == "+", "+") + if self.settings == "dash": + return (sym == "-", "-") + if self.settings == "single": if self.lastSym: return (self.lastSym == sym, self.lastSym) else: @@ -173,16 +295,16 @@ def testsingle(self, sym): return (None, None) def testcyc(self, sym, lv): - if self.settings == 'cyclic': + if self.settings == "cyclic": if self.lvs[lv]: return (self.lvs[lv] == sym, self.lvs[lv]) else: - if (sym not in self.lvs): + if sym not in self.lvs: self.lvs[lv] = sym return (True, None) else: return (False, None) - if self.settings == 'any': + if self.settings == "any": if self.lvs[lv]: return self.lvs[lv] == sym else: @@ -193,9 +315,9 @@ def testcyc(self, sym, lv): class md005(mddef): flag = re.M - desc = 'Inconsistent indentation for list items at the same level' - locator = r'^([ ]{0,3})[*+-](?=\s)' - eol = r'^(?=\S)' + desc = "Inconsistent indentation for list items at the same level" + locator = r"^([ ]{0,3})[*+-](?=\s)" + eol = r"^(?=\S)" gid = 1 lastpos = -1 @@ -219,27 +341,27 @@ def test(self, text, s, e): ret = {} lvstack = [] - sym = text[e:e + 1] + # sym = text[e:e + 1] nspaces = e - s basenspaces = e - s (ans, exp) = self.spacecheck(-1, nspaces) if not ans: - ret[s] = '%s expected, %s found' % (exp, nspaces) + ret[s] = "%s expected, %s found" % (exp, nspaces) - rest = text[e + 1:] + rest = text[e + 1 :] mr = re.search(self.eol, rest, re.M) end = mr.start(0) if mr else len(rest) block = rest[:end] # print('====') # print(block) # print('====') - mrs = re.finditer(r'^( *)([*\-+])\s+', block, re.M) + mrs = re.finditer(r"^( *)([*\-+])\s+", block, re.M) for mr in mrs: # print('----') # print(mr.group(2)) # print('----') self.lastpos = e + 1 + mr.end(0) - sym = mr.group(2) + # sym = mr.group(2) nspaces = len(mr.group(1)) if nspaces < basenspaces: lv = 0 @@ -255,16 +377,15 @@ def test(self, text, s, e): lvstack.append(nspaces) (ans, exp) = self.spacecheck(lv, nspaces) if ans is False: - ret[e + 1 + - mr.start(2)] = '%s expected, %s found' % (exp, nspaces) + ret[e + 1 + mr.start(2)] = "%s expected, %s found" % (exp, nspaces) return ret class md006(mddef): flag = re.M - desc = 'Consider starting bulleted lists at the beginning of the line' - locator = r'^([ ]{0,3})[*+-](?=\s)' - eol = r'^(?=\S)' + desc = "Consider starting bulleted lists at the beginning of the line" + locator = r"^([ ]{0,3})[*+-](?=\s)" + eol = r"^(?=\S)" gid = 1 lastpos = -1 @@ -275,20 +396,20 @@ def test(self, text, s, e): self.lastpos = e ret = {} - lvstack = [] - sym = text[e:e + 1] + # lvstack = [] + # sym = text[e:e + 1] nspaces = e - s if nspaces > 0: - ret[s] = '%d found' % nspaces + ret[s] = "%d found" % nspaces - rest = text[e + 1:] + rest = text[e + 1 :] mr = re.search(self.eol, rest, re.M) end = mr.start(0) if mr else len(rest) block = rest[:end] # print('====') # print(block) # print('====') - mrs = re.finditer(r'^(\s*)([*\-+])\s+', block, re.M) + mrs = re.finditer(r"^(\s*)([*\-+])\s+", block, re.M) for mr in mrs: # print('----') # print(mr.group(2)) @@ -299,9 +420,9 @@ def test(self, text, s, e): class md007(mddef): flag = re.M - desc = 'Unordered list indentation' - locator = r'^([ ]{0,3})[*+-](?=\s)' - eol = r'^(?=\S)' + desc = "Unordered list indentation" + locator = r"^([ ]{0,3})[*+-](?=\s)" + eol = r"^(?=\S)" gid = 1 lastpos = -1 @@ -312,7 +433,7 @@ def __init__(self, settings, view): self.settings = settings def spacecheck(self, nspaces): - return (nspaces % self.settings == 0, '%d*n' % self.settings) + return (nspaces % self.settings == 0, "%d*n" % self.settings) def test(self, text, s, e): # print(self.lastpos) @@ -324,16 +445,16 @@ def test(self, text, s, e): nspaces = e - s (ans, exp) = self.spacecheck(nspaces) if not ans: - ret[s] = '%s expected, %s found' % (exp, nspaces) + ret[s] = "%s expected, %s found" % (exp, nspaces) - rest = text[e + 1:] + rest = text[e + 1 :] mr = re.search(self.eol, rest, re.M) end = mr.start(0) if mr else len(rest) block = rest[:end] # print('====') # print(block) # print('====') - mrs = re.finditer(r'^( *)([*\-+])\s+', block, re.M) + mrs = re.finditer(r"^( *)([*\-+])\s+", block, re.M) for mr in mrs: # print('----') # print(mr.group(2)) @@ -342,50 +463,49 @@ def test(self, text, s, e): nspaces = len(mr.group(1)) (ans, exp) = self.spacecheck(nspaces) if ans is False: - ret[e + 1 + - mr.start(2)] = '%s expected, %s found' % (exp, nspaces) + ret[e + 1 + mr.start(2)] = "%s expected, %s found" % (exp, nspaces) return ret class md009(mddef): flag = re.M - desc = 'Trailing spaces' - locator = r' +$' + desc = "Trailing spaces" + locator = r" +$" def test(self, text, s, e): - return {s: '%d spaces' % (e - s)} + return {s: "%d spaces" % (e - s)} class md010(mddef): flag = re.M - desc = 'Hard tabs' - locator = r'\t' + desc = "Hard tabs" + locator = r"\t" def test(self, text, s, e): - return {s: 'hard tab found'} + return {s: "hard tab found"} class md011(mddef): flag = re.M - desc = 'Reversed link syntax' - locator = r'\(.*?\)\[.*?\]' + desc = "Reversed link syntax" + locator = r"\(.*?\)\[.*?\]" def test(self, text, s, e): - return {s: 'reversed link syntax found'} + return {s: "reversed link syntax found"} class md012(mddef): - desc = 'Multiple consecutive blank lines' - locator = r'\n{3,}' + desc = "Multiple consecutive blank lines" + locator = r"\n{3,}" def test(self, text, s, e): - return {s + 1: '%d blank lines' % (e - s - 1)} + return {s + 1: "%d blank lines" % (e - s - 1)} class md013(mddef): flag = re.M - desc = 'Line length' - locator = r'^.+$' + desc = "Line length" + locator = r"^.+$" def __init__(self, settings, view): if settings == 0: @@ -395,95 +515,94 @@ def __init__(self, settings, view): def test(self, text, s, e): t = text[s:e] - if not re.match(r'^[ ]*[>\+\-\*].+$', t): + if not re.match(r"^[ ]*[>\+\-\*].+$", t): if e - s > self.settings: - return {s: '%d characters' % (e - s)} + return {s: "%d characters" % (e - s)} return {} class md018(mddef): flag = re.M - desc = 'No space after hash on atx style header' - locator = r'^#{1,6}(?![#\s]).*(? 1 and ((t[0] == ' ' and t[1] == ' ') or - (t[-1] == ' ' and t[-2] == ' ')): - return {s: 'too many spaces'} + if len(t) > 1 and ((t[0] == " " and t[1] == " ") or (t[-1] == " " and t[-2] == " ")): + return {s: "too many spaces"} return {} class md022(mddef): flag = re.M - desc = 'Headers should be surrounded by blank lines' - locator = r'^((?:-+|=+)|(?:#{1,6}(?!#).*))$' + desc = "Headers should be surrounded by blank lines" + locator = r"^((?:-+|=+)|(?:#{1,6}(?!#).*))$" def test(self, text, s, e): - if re.match(r'-+|=+', text[s:e]): - st = text.rfind('\n', 0, s - 1) + if re.match(r"-+|=+", text[s:e]): + st = text.rfind("\n", 0, s - 1) s = st + 1 - if s > 1 and text[s - 2] != '\n': - return {s: 'blank line required before this line'} + if s > 1 and text[s - 2] != "\n": + return {s: "blank line required before this line"} - if e < len(text) - 2 and text[e + 1] != '\n': - return {s: 'blank line required after this line'} + if e < len(text) - 2 and text[e + 1] != "\n": + return {s: "blank line required after this line"} return {} class md023(mddef): flag = re.M - desc = 'Headers must start at the beginning of the line' - locator = r'^( +)((?:-+|=+)|(?:#{1,6}(?!#).*))$' + desc = "Headers must start at the beginning of the line" + locator = r"^( +)((?:-+|=+)|(?:#{1,6}(?!#).*))$" gid = 1 def test(self, text, s, e): - return {s: '%d spaces found' % (e - s)} + return {s: "%d spaces found" % (e - s)} class md024(mddef): flag = re.M - desc = 'Multiple headers with the same content' - locator = r'^((?:-+|=+)|(?:#{1,6}(?!#).*))$' + desc = "Multiple headers with the same content" + locator = r"^((?:-+|=+)|(?:#{1,6}(?!#).*))$" gid = 1 - ratx = r'(#{1,6}(?!#)) *(.*?) *$' - ratxc = r'(#{1,6}(?!#)) *(.*?) *(#+)$' + ratx = r"(#{1,6}(?!#)) *(.*?) *$" + ratxc = r"(#{1,6}(?!#)) *(.*?) *(#+)$" def __init__(self, settings, view): super(md024, self).__init__(settings, view) @@ -492,9 +611,9 @@ def __init__(self, settings, view): def test(self, text, s, e): ret = {} title = text[s:e] - if re.match(r'-+|=+', title): - st = text.rfind('\n', 0, s - 1) - title = text[st + 1: s - 1] + if re.match(r"-+|=+", title): + st = text.rfind("\n", 0, s - 1) + title = text[st + 1 : s - 1] else: mr = re.match(self.ratxc, title) if mr: @@ -503,7 +622,7 @@ def test(self, text, s, e): mr = re.match(self.ratx, title) title = mr.group(2) if title in self.storage: - ret[s] = '%s duplicated' % repr(title) + ret[s] = "%s duplicated" % repr(title) else: self.storage.append(title) return ret @@ -511,33 +630,33 @@ def test(self, text, s, e): class md025(mddef): flag = re.M - desc = 'Multiple top level headers in the same document' - locator = r'^(={3,}|#(?!#).*)$' + desc = "Multiple top level headers in the same document" + locator = r"^(={3,}|#(?!#).*)$" count = 0 def test(self, text, s, e): ret = {} self.count += 1 if self.count > 1: - ret[s] = '%d found' % self.count + ret[s] = "%d found" % self.count return ret class md026(mddef): flag = re.M - desc = 'Trailing punctuation in header' - locator = r'^((?:-+|=+)|(?:#{1,6}(?!#).*))$' + desc = "Trailing punctuation in header" + locator = r"^((?:-+|=+)|(?:#{1,6}(?!#).*))$" gid = 1 - ratx = r'(#{1,6}(?!#)) *(.*?) *$' - ratxc = r'(#{1,6}(?!#)) *(.*?) *?(#+)$' + ratx = r"(#{1,6}(?!#)) *(.*?) *$" + ratxc = r"(#{1,6}(?!#)) *(.*?) *?(#+)$" def test(self, text, s, e): ret = {} title = text[s:e] - if re.match(r'-+|=+', title): - st = text.rfind('\n', 0, s - 1) - title = text[st + 1: s - 1] + if re.match(r"-+|=+", title): + st = text.rfind("\n", 0, s - 1) + title = text[st + 1 : s - 1] else: mr = re.match(self.ratxc, title) if mr: @@ -546,40 +665,48 @@ def test(self, text, s, e): mr = re.match(self.ratx, title) title = mr.group(2) if len(title) > 0 and title[-1] in self.settings: - ret[s] = '%s found' % repr(title[-1]) + ret[s] = "%s found" % repr(title[-1]) return ret class md027(mddef): flag = re.M - desc = 'Multiple spaces after blockquote symbol' - locator = r'^ {0,4}> {2,}' + desc = "Multiple spaces after blockquote symbol" + locator = r"^ {0,4}> {2,}" + list_indent = 0 def test(self, text, s, e): - return {s: 'too many spaces'} + ret = {} + match = re.search(r"^ {0,4}>( {2,}(?:[-+*]|[0-9]+\.)\s)", text[s : s + 100]) + if match: + self.list_indent = len(match.group(1)) + print("indent", self.list_indent) + elif e - s - 1 != self.list_indent: + ret[s] = "too many spaces" + return ret class md028(mddef): flag = re.M - desc = 'Blank line inside blockquote' - locator = r'^ {0,4}>.*$' + desc = "Blank line inside blockquote" + locator = r"^ {0,4}>.*$" lastQuoteEnd = None def test(self, text, s, e): ret = {} if self.lastQuoteEnd: - if re.match(r'(\n *){2,}', text[self.lastQuoteEnd:s]): - ret[self.lastQuoteEnd] = 'found one' + if re.match(r"^(\n *){2,}$", text[self.lastQuoteEnd : s]): + ret[self.lastQuoteEnd] = "found one" self.lastQuoteEnd = e return ret class md029(mddef): flag = re.M - desc = 'Ordered list item prefix' - locator = r'^ {0,3}([0-9]+)\.(?=\s)' + desc = "Ordered list item prefix" + locator = r"^ {0,3}([0-9]+)\.(?=\s)" gid = 1 - eol = r'^\s*$' + eol = r"^\s*$" lastpos = -1 def test(self, text, s, e): @@ -588,193 +715,70 @@ def test(self, text, s, e): self.lastpos = e sym = text[s:e] - if self.settings == 'any': - if sym == '1': + if self.settings == "any": + if sym == "1": style = None else: - style = 'ordered' - elif self.settings == 'one': - style = 'one' - elif self.settings == 'ordered': - style = 'ordered' + style = "ordered" + elif self.settings == "one": + style = "one" + elif self.settings == "ordered": + style = "ordered" - rest = text[e + 1:] + rest = text[e + 1 :] mr = re.search(self.eol, rest, re.M) end = mr.start(0) if mr else len(rest) block = rest[:end] - mrs = re.finditer(r'^ {0,3}([0-9]+)\.(?=\s)', block, re.M) + mrs = re.finditer(r"^ {0,3}([0-9]+)\.(?=\s)", block, re.M) lastSym = sym ret = {} for mr in mrs: self.lastpos = e + 1 + mr.end(0) sym = mr.group(1) if style is None: - if sym == '1': - style = 'one' + if sym == "1": + style = "one" else: - style = 'ordered' + style = "ordered" - if style == 'one': - if sym != '1': - ret[mr.start(1) + e + - 1] = '%s found, \'1\' expected' % repr(sym) + if style == "one": + if sym != "1": + ret[mr.start(1) + e + 1] = "%s found, '1' expected" % repr(sym) else: if int(sym) != int(lastSym) + 1: - ret[mr.start(1) + e + 1] = ('%s found, \'%d\' expected' % - (repr(sym), int(lastSym) + 1)) + ret[mr.start(1) + e + 1] = "%s found, '%d' expected" % ( + repr(sym), + int(lastSym) + 1, + ) lastSym = sym return ret class md030(mddef): flag = re.M - desc = 'Ordered list item prefix' - locator = r'^ {0,3}(([0-9]+\.)|[*+-])(?=\s)' + desc = "Ordered list item prefix" + locator = r"^ {0,3}(([0-9]+\.)|[*+-])(?=\s)" gid = 1 def test(self, text, s, e): sym = text[s:e] - mr = re.match(r'[0-9]+\.', sym) + mr = re.match(r"[0-9]+\.", sym) if mr: - single = self.settings['ol_single'] - multi = self.settings['ol_multi'] + single = self.settings["ol_single"] + multi = self.settings["ol_multi"] else: - single = self.settings['ul_single'] - multi = self.settings['ul_multi'] + single = self.settings["ul_single"] + multi = self.settings["ul_multi"] nspaces = 0 p = e - while text[p] == ' ': + while text[p] == " ": p += 1 nspaces += 1 - while text[p] != '\n' and text[p] != '\r': + while text[p] != "\n" and text[p] != "\r": p += 1 ret = {} - is_multi = (len(text) >= p + 2) and (text[p + 1] in '\r\n') + is_multi = (len(text) >= p + 2) and (text[p + 1] in "\r\n") against_value = multi if is_multi else single if against_value != nspaces: - ret[e] = '%d spaces found, %d expected' % (nspaces, against_value) - return ret - - -class MarkdownLintCommand(MDETextCommand): - - blockdef = [] - scope_block = 'markup.raw.block.markdown' - - def run(self, edit): - mddef = globals()['mddef'] - text = self.view.substr(sublime.Region(0, self.view.size())) - st = self.view.settings().get('mde.lint', {}) - uselist = [] - disablelist = st['disable'] - for cl in mddef.__subclasses__(): - if cl.__name__ not in disablelist: - uselist.append(cl) - result = [] - for mddef in uselist: - r = self.test(mddef(st[mddef.__name__] if mddef.__name__ in st - else None, self.view), text) - result.extend(r) - sublime.status_message('MarkdownLint: %d error(s) found' % len(result)) - if len(result) > 0: - result = sorted(result, key=lambda t: t[0]) - outputtxt = '' - for t in result: - (row, col) = self.view.rowcol(t[0]) - outputtxt += 'line %d: %s, %s\n' % (row + 1, t[1], t[2]) - window = sublime.active_window() - output = window.create_output_panel("mde") - output.run_command('erase_view') - output.run_command('append', {'characters': outputtxt}) - window.run_command("show_panel", {"panel": "output.mde"}) - - def test(self, tar, text): - loc = tar.locator - # print(tar) - # print(repr(loc)) - it = re.finditer(loc, text, tar.flag) - ret = [] - for mr in it: - # print('find %d,%d' % (mr.start(tar.gid), mr.end(tar.gid))) - if self.scope_block in self.view.scope_name(mr.start(0)): - if tar.__class__ not in self.blockdef: - continue - ans = tar.test(text, mr.start(tar.gid), mr.end(tar.gid)) - for p in ans: - ret.append((p, str(tar), ans[p])) - # (row, col) = self.view.rowcol(p) - # print('line %d: %s, %s' % (row + 1, tar, ans[p])) - - # if not ans: - # ret = False - # (row, col) = self.view.rowcol(mr.start(tar.gid)) - # print('line %d: %s ' % (row + 1, tar)) - if tar.finish: - break - + ret[e] = "%d spaces found, %d expected" % (nspaces, against_value) return ret - -import platform -import sys -import subprocess -ON_WINDOWS = platform.system() is 'Windows' -ST2 = sys.version_info < (3, 0) - - -class MarkdownLintMdlCommand(MDETextCommand): - - def run(self, edit): - try: - st = self.view.settings().get('mde.lint', {}) - mdl_config = st['mdl'] or {} - sublime.status_message("Linting file...") - textContent = self.view.substr(sublime.Region(0, self.view.size())) - textContent = textContent.encode('utf-8') - executable_name = mdl_config['executable'] - if not executable_name: - executable_name = "mdl.bat" if ON_WINDOWS else "mdl" - additional_arguments = mdl_config['additional_arguments'] or [] - # call mdl version - process = subprocess.Popen([executable_name] + additional_arguments, - bufsize=1024 * 1024 + len(textContent), - stdin=subprocess.PIPE, - stdout=subprocess.PIPE, - stderr=subprocess.PIPE, - startupinfo=self.getStartupInfo()) - stdout, stderr = process.communicate(textContent) - if stderr: - result = False - error = self.readResult(stderr) - outputtxt = error - else: - result = self.readResult(stdout) - outputtxt = result - sublime.status_message( - 'MarkdownLint: %d error(s) found' % len(result.split('\n'))) - window = sublime.active_window() - output = window.create_output_panel("mde") - output.run_command('erase_view') - output.run_command('append', {'characters': outputtxt}) - window.run_command("show_panel", {"panel": "output.mde"}) - - except OSError as e: - print(e) - sublime.error_message( - "It looks like markdownlint is not installed.\nPlease make sure that it is installed and globally accessible as `mdl`.") - except Exception as e: - print(e) - - def readResult(self, stdout): - if ST2: - r = stdout.decode('utf-8') - else: - r = str(stdout, encoding='utf-8') - return r.strip().replace('\r', '').replace('(stdin):', '') - - def getStartupInfo(self): - if ON_WINDOWS: - info = subprocess.STARTUPINFO() - info.dwFlags |= subprocess.STARTF_USESHOWWINDOW - info.wShowWindow = subprocess.SW_HIDE - return info - return None diff --git a/plugins/lists.py b/plugins/lists.py new file mode 100644 index 00000000..8726130a --- /dev/null +++ b/plugins/lists.py @@ -0,0 +1,295 @@ +import re +import sublime + +from .view import MdeTextCommand + + +class MdeBaseUnIndentListItemCommand(MdeTextCommand): + """ + This is an interanal text command class shared by `(un)indent_list_item` commands. + + It is responsible to read settings and cycle through all selections to replace text. + """ + + def run(self, edit): + queue = [] + + view = self.view + settings = view.settings() + bullets = settings.get("mde.list_indent_bullets", ["*", "-", "+"]) + if settings.get("mde.list_indent_auto_switch_bullet", True): + new_bullets = bullets + else: + new_bullets = None + + if settings.get("translate_tabs_to_spaces"): + tab_str = " " * settings.get("tab_size", 4) + else: + tab_str = "\t" + + pattern = re.compile( + r"^(?:[\s>]*>\s)?(\s*)(?:([%s])\s)?" % "".join(re.escape(bullet) for bullet in bullets) + ) + + for sel in view.sel(): + for region in view.split_by_newlines(view.line(sel)): + match = re.search(pattern, view.substr(region)) + if not match: + continue + + indent, bullet = match.groups() + text = self.compute_replacement(indent, tab_str, bullet, new_bullets) + if text is None: + continue + + # setup region to replace based on pattern match + region.b = region.a + max(match.end(1), match.end(2)) + region.a += match.start(1) + + queue.append([region, text]) + + for r, text in reversed(queue): + view.replace(edit, r, text) + + def compute_replacement(self, indent, tab_str, bullet, bullets): + raise RuntimeError + + +class MdeIndentListItemCommand(MdeBaseUnIndentListItemCommand): + """ + The `mde_indent_list_item` command indents unordered list items. + + It indents lists within blockquotes. + It changes list bullet according to indentation level + if `mde.list_indent_auto_switch_bullet` is set `true`. + """ + + def compute_replacement(self, indent, tab_str, bullet, bullets): + text = indent + tab_str + if bullet: + if bullets: + text += bullets[(bullets.index(bullet) + 1) % len(bullets)] + else: + text += bullet + return text + + +class MdeUnindentListItemCommand(MdeBaseUnIndentListItemCommand): + """ + The `mde_unindent_list_item` command unindents unordered list items. + + It unindents lists within blockquotes. + It changes list bullet according to indentation level. + if `mde.list_indent_auto_switch_bullet` is set `true`. + """ + + def compute_replacement(self, indent, tab_str, bullet, bullets): + if not indent: + return None + + text = indent.replace(tab_str, "", 1) + if bullet: + if bullets: + text += bullets[(bullets.index(bullet) - 1) % len(bullets)] + else: + text += bullet + return text + + +class MdeSwitchListBulletTypeCommand(MdeTextCommand): + """ + The `mde_switch_list_bullet_type` command converts selected list items to ordered and unordered. + + Each selected item is evaluated separately. + """ + + def run(self, edit): + align_text = self.view.settings().get("mde.list_align_text", True) + auto_increment = self.view.settings().get("mde.auto_increment_ordered_list_number", True) + bullets = self.view.settings().get("mde.list_indent_bullets", ["*", "-", "+"]) + pattern = re.compile( + r"^\s*(?:>\s*)*(?:([%s])|(\d+[.)]))(\s+)" + % "".join(re.escape(bullet) for bullet in bullets) + ) + + for sel in self.view.sel(): + idx = 1 + for region in self.view.split_by_newlines(self.view.line(sel)): + text = self.view.substr(region) + match = pattern.search(text) + if not match: + continue + + bullet, number, space = match.groups() + if bullet: + # Transform unordered to ordered list + new_text = str(idx) + "." + if auto_increment: + idx += 1 + + region.a += match.start(1) + region.b = region.a + min(len(new_text), max(1, len(space))) + self.view.replace(edit, region, new_text) + + elif number: + # Transform ordered to unordered list + region.a += match.start(2) + if align_text: + new_text = bullets[0] + " " * len(number) + region.b = region.a + len(new_text) + else: + new_text = bullets[0] + region.b = region.a + len(number) + self.view.replace(edit, region, new_text) + + +class MdeNumberListCommand(MdeTextCommand): + """ + This class describes the `mde_number_list` command. + """ + + def run(self, edit): + view = self.view + auto_increment = view.settings().get("mde.auto_increment_ordered_list_number", True) + pattern = re.compile(r"^([ \t>]*)(\d+)([.)])([ \t]+|$)") + + for sel in view.sel(): + to_insert = "\n" + + line = view.line(sel) + col = sel.begin() - line.begin() + + match = pattern.search(view.substr(line)) + if match: + quote, number, punct, space = match.groups() + next_number = str(int(number) + 1) if auto_increment else number + + num_spaces = max(1, len(space) - (len(next_number) - len(number))) + # caret is in front of item text + if col < match.end(): + num_spaces -= match.end() - col + + to_insert += quote + next_number + punct + " " * num_spaces + + view.erase(edit, sel) + view.insert(edit, sel.begin(), to_insert) + + +class MdeToggleTaskListItemCommand(MdeTextCommand): + """ + The `mde_toggle_task_list_item` command toggles the check mark of task list items. + + It must be called in the line of the check mark. + + **Examples:** + + ```markdown + # Orderd Task List + + 1. [ ] task 1 + 2. [X] task 2 + + # Unorderd Task List + + * [ ] task 1 + - [X] task 2 + + [ ] task 3 + + # Quoted Task List + + > * [ ] task 1 + > * [X] task 2 + ``` + """ + + def run(self, edit): + pattern = re.compile( + r""" + ^[ \t>]* # leading blockquote or whitespace + (?: [-+*] | \d+[.)] ) # unordered or ordered list bullet + (?: [ \t]+\[([ xX])\] ) # GFM task checkbox + (?: [ \t]+ | $ ) # at least one space,tab or eol + """, + re.X, + ) + + for sel in self.view.sel(): + for region in self.view.split_by_newlines(self.view.line(sel)): + region.b = min(region.b, region.a + 50) + match = pattern.search(self.view.substr(region)) + if not match: + continue + + # calculate text position of check mark + region.a += match.start(1) + region.b = region.a + 1 + + self.view.replace(edit, region, "X" if match.group(1) == " " else " ") + + +class MdeJoinLines(MdeTextCommand): + """ + This class describes a `mde_join_lines` command. + + It removes any leading list or blockquote punctuation from any line after a + caret and the linefeed separating it from a line a caret is placed within. + + It is meant to be bound to `"delete"` key when caret is at eol. + """ + + def run(self, edit): + view = self.view + pattern = re.compile( + r""" + ^ + ([ \t>]*) # leading blockquote or whitespace + ( + (?:[-+*]|\d+[.)]) # unordered or ordered list bullet + (?:[ \t]+\[[ xX]\])? # optional GFM task checkbox + (?:[ \t]+|$) # at least one space,tab or eol + )? + (\S|$) # first char of content, if any + """, + re.X, + ) + + for sel in view.sel(): + pt = sel.begin() + if len(sel) == 0: + # join current with following line + lines = [view.line(sel)] + _, col = view.rowcol(pt) + else: + # join all selected lines beginning with the one before the last + lines = reversed(view.split_by_newlines(view.line(sel))[:-1]) + col = None + + for line in lines: + eol = line.end() + eol_ws = eol == 0 or view.substr(eol - 1) in (" ", "\t", "\n") + + # mark newline for deletion + to_delete = 1 + + next_line_matches = pattern.search(view.substr(view.line(eol + 1))) + if next_line_matches: + if ( + # selected text block + col is None + # caret is within list item paragraph + or col > next_line_matches.start(2) + # caret followed by content (not only whitespace or blockquote signs) + or any(ch not in " \t>" for ch in view.substr(sublime.Region(pt, eol))) + ): + # mark blockquote and list bullets for deletion + to_delete += next_line_matches.start(3) + else: + # mark blockquote for deletion + to_delete += next_line_matches.start(2) + + # maintain at least one space between tokens (convert newline to space so to say) + if eol_ws is False and next_line_matches.end(3) > next_line_matches.start(3): + view.replace(edit, sublime.Region(eol, eol + to_delete), " ") + continue + + view.erase(edit, sublime.Region(eol, eol + to_delete)) diff --git a/plugins/logging.py b/plugins/logging.py new file mode 100644 index 00000000..bfe3ea7f --- /dev/null +++ b/plugins/logging.py @@ -0,0 +1,41 @@ +import logging +import sublime + +PACKAGE_NAME = __package__.split(".", 1)[0] + +logging.basicConfig(level=logging.ERROR, format="%(name)s [%(levelname)s]: %(message)s") +logger = logging.getLogger(PACKAGE_NAME) + + +def load_logger(): + """ + Subscribe to Preferences changes in to get log level from user settings. + + Must be called in plugin_loaded(). + """ + settings = sublime.load_settings("Preferences.sublime-settings") + settings.clear_on_change(__name__) + settings.add_on_change(__name__, on_preferences_changed) + on_preferences_changed() + + +def unload_logger(): + """ + Unsubscribe to Preferences changes. + + Must be called in plugin_unloaded(). + """ + settings = sublime.load_settings("Preferences.sublime-settings") + settings.clear_on_change(__name__) + + +def on_preferences_changed(): + """ + Update log level according to user settings + """ + settings = sublime.load_settings("Preferences.sublime-settings") + + try: + logger.setLevel(settings.get("mde.logging.level", "ERROR")) + except (TypeError, ValueError): + logger.setLevel(logging.ERROR) diff --git a/quote_indenting.py b/plugins/quotes.py similarity index 73% rename from quote_indenting.py rename to plugins/quotes.py index f254d7da..9a977480 100644 --- a/quote_indenting.py +++ b/plugins/quotes.py @@ -1,17 +1,10 @@ import re import sublime -import sublime_plugin -try: - from MarkdownEditing.mdeutils import * -except ImportError: - from mdeutils import * +from .view import MdeTextCommand -class IndentQuote(MDETextCommand): - - def description(self): - return 'Indent a quote' +class MdeIndentQuote(MdeTextCommand): def run(self, edit): view = self.view selections = view.sel() @@ -33,18 +26,18 @@ def run(self, edit): replacement_text = "\n".join(all_lines) view.replace(edit, expanded_selection, replacement_text) - new_selections.append(sublime.Region(expanded_selection_start, expanded_selection_start + len(replacement_text))) + new_selections.append( + sublime.Region( + expanded_selection_start, expanded_selection_start + len(replacement_text) + ) + ) selections.clear() for selection in new_selections: selections.add(selection) -class DeindentQuote(MDETextCommand): - - def description(self): - return 'Deindent a quote' - +class MdeUnindentQuote(MdeTextCommand): def run(self, edit): view = self.view selections = view.sel() @@ -59,14 +52,18 @@ def run(self, edit): complete_line = view.line(line) expanded_selection_end = complete_line.end() text = view.substr(complete_line) - all_lines.append(re.sub(r'^(> )', '', text)) + all_lines.append(re.sub(r"^(> )", "", text)) expanded_selection = sublime.Region(expanded_selection_start, expanded_selection_end) replacement_text = "\n".join(all_lines) view.replace(edit, expanded_selection, replacement_text) - new_selections.append(sublime.Region(expanded_selection_start, expanded_selection_start + len(replacement_text))) + new_selections.append( + sublime.Region( + expanded_selection_start, expanded_selection_start + len(replacement_text) + ) + ) selections.clear() for selection in new_selections: diff --git a/references.py b/plugins/references.py similarity index 60% rename from references.py rename to plugins/references.py index 7dbb7544..d932bc54 100644 --- a/references.py +++ b/plugins/references.py @@ -2,26 +2,25 @@ Commands related to links, references and footnotes. Exported commands: - ReferenceJumpCommand - ReferenceJumpContextCommand - ReferenceNewReferenceCommand - ReferenceNewInlineLinkCommand - ReferenceNewInlineImage - ReferenceNewImage - ReferenceNewFootnote - ReferenceDeleteReference - ReferenceOrganize - GatherMissingLinkMarkersCommand - ConvertInlineLinkToReferenceCommand - ConvertInlineLinksToReferencesCommand + MdeReferenceJumpCommand + MdeReferenceJumpContextCommand + MdeReferenceNewReferenceCommand + MdeReferenceNewInlineLinkCommand + MdeReferenceNewInlineImageCommand + MdeReferenceNewImageCommand + MdeReferenceNewFootnoteCommand + MdeReferenceDeleteReferenceCommand + MdeReferenceOrganizeCommand + MdeGatherMissingLinkMarkersCommand + MdeConvertInlineLinkToReferenceCommand + MdeConvertInlineLinksToReferencesCommand """ import sublime import re import operator -try: - from MarkdownEditing.mdeutils import MDETextCommand -except ImportError: - from mdeutils import MDETextCommand + +from .view import MdeTextCommand +from .view import MdeViewEventListener refname_scope_name = "constant.other.reference.link.markdown" definition_scope_name = "meta.link.reference.def.markdown" @@ -50,29 +49,34 @@ def __init__(self, **kwargs): self.__dict__.update(kwargs) -def getMarkers(view, name=''): +def getMarkers(view, name=""): """Find all markers.""" # returns {name -> Region} markers = [] name = re.escape(name) - if name == '': + if name == "": markers.extend(view.find_all(r"(?<=\]\[)([^\]]+)(?=\])", 0)) # ][???] markers.extend(view.find_all(r"(?<=\[)([^\]]*)(?=\]\[\])", 0)) # [???][] markers.extend(view.find_all(r"(?<=\[)(\^[^\]]+)(?=\])(?!\s*\]:)", 0)) # [^???] - markers.extend(view.find_all(r"(? Region} refs = [] name = re.escape(name) - if name == '': + if name == "": refs.extend(view.find_all(r"(?<=^\[)([^\]]+)(?=\]:)", 0)) else: refs.extend(view.find_all(r"(?<=^\[)(%s)(?=\]:)" % name, 0)) @@ -114,24 +118,28 @@ def isMarkerDefined(view, name): def getCurrentScopeRegion(view, pt): """Extend the region under current scope.""" scope = view.scope_name(pt) - l = pt - while l > 0 and view.scope_name(l - 1) == scope: - l -= 1 - r = pt - while r < view.size() and view.scope_name(r) == scope: - r += 1 - return sublime.Region(l, r) + start = pt + while start > 0 and view.scope_name(start - 1) == scope: + start -= 1 + end = pt + while end < view.size() and view.scope_name(end) == scope: + end += 1 + return sublime.Region(start, end) def findScopeFrom(view, pt, scope, backwards=False, char=None): """Find the nearest position of a scope from given position.""" if backwards: - while pt >= 0 and (not hasScope(view.scope_name(pt), scope) or - (char is not None and view.substr(pt) != char)): + while pt >= 0 and ( + not hasScope(view.scope_name(pt), scope) + or (char is not None and view.substr(pt) != char) + ): pt -= 1 else: - while pt < view.size() and (not hasScope(view.scope_name(pt), scope) or - (char is not None and view.substr(pt) != char)): + while pt < view.size() and ( + not hasScope(view.scope_name(pt), scope) + or (char is not None and view.substr(pt) != char) + ): pt += 1 return pt @@ -151,7 +159,11 @@ def get_reference(view, pos): marker_pt = findScopeFrom(view, pos, refname_scope_name, True) defname = view.substr(getCurrentScopeRegion(view, marker_pt)) return (True, True, defname) - elif marker_scope_name in scope or marker_image_scope_name in scope or marker_literal_scope_name in scope: + elif ( + marker_scope_name in scope + or marker_image_scope_name in scope + or marker_literal_scope_name in scope + ): if refname_scope_name in scope: # defname name defname = view.substr(getCurrentScopeRegion(view, pos)) @@ -159,12 +171,18 @@ def get_reference(view, pos): # Text if marker_begin_scope_name in scope: pos += 1 - while pos >= 0 and view.substr(sublime.Region(pos, pos + 1)) in '[]': + while pos >= 0 and view.substr(sublime.Region(pos, pos + 1)) in "[]": pos -= 1 - if not (marker_scope_name in scope or marker_image_scope_name in scope or marker_literal_scope_name in scope): + if not ( + marker_scope_name in scope + or marker_image_scope_name in scope + or marker_literal_scope_name in scope + ): return (False, None, None) marker_text_end = findScopeFrom(view, pos, marker_text_end_scope_name) + 1 - if hasScope(view.scope_name(marker_text_end), refname_start_scope_name) and not hasScope(view.scope_name(marker_text_end + 1), marker_end_scope_name): + if hasScope( + view.scope_name(marker_text_end), refname_start_scope_name + ) and not hasScope(view.scope_name(marker_text_end + 1), marker_end_scope_name): # of [Text][name] struct marker_pt = marker_text_end + 1 marker_pt_end = findScopeFrom(view, marker_pt, marker_end_scope_name) @@ -177,12 +195,12 @@ def get_reference(view, pos): return (False, None, None) -class ReferenceJumpCommand(MDETextCommand): +class MdeReferenceJumpCommand(MdeTextCommand): """Jump between definition and reference.""" def description(self): """Description for package control.""" - return 'Jump between definition and reference' + return "Jump between definition and reference" def run(self, edit): """Run command callback.""" @@ -214,24 +232,43 @@ def run(self, edit): if len(missing_refs) + len(missing_markers) > 0: # has something missing if len(missing_markers) == 0: - sublime.status_message("The definition%s of %s cannot be found." % ("" if len(missing_refs) == 1 else "s", ", ".join(missing_refs))) + sublime.status_message( + "The definition%s of %s cannot be found." + % ("" if len(missing_refs) == 1 else "s", ", ".join(missing_refs)) + ) elif len(missing_refs) == 0: - sublime.status_message("The marker%s of %s cannot be found." % ("" if len(missing_markers) == 1 else "s", ", ".join(missing_markers))) + sublime.status_message( + "The marker%s of %s cannot be found." + % ("" if len(missing_markers) == 1 else "s", ", ".join(missing_markers)) + ) else: - sublime.status_message("The definition%s of %s and the marker%s of %s cannot be found." % ("" if len(missing_refs) == 1 else "s", ", ".join(missing_refs), "" if len(missing_markers) == 1 else "s", ", ".join(missing_markers))) - - -class ReferenceJumpContextCommand(ReferenceJumpCommand): + sublime.status_message( + "The definition%s of %s and the marker%s of %s cannot be found." + % ( + "" if len(missing_refs) == 1 else "s", + ", ".join(missing_refs), + "" if len(missing_markers) == 1 else "s", + ", ".join(missing_markers), + ) + ) + + +class MdeReferenceJumpContextCommand(MdeReferenceJumpCommand): """Jump between definition and reference. Used in context menu.""" def is_visible(self): """Return True if cursor is on a marker or reference.""" - return ReferenceJumpCommand.is_visible(self) and any(get_reference(self.view, sel.begin())[0] for sel in self.view.sel()) + return MdeReferenceJumpCommand.is_visible(self) and any( + get_reference(self.view, sel.begin())[0] for sel in self.view.sel() + ) def is_url(contents): """Return if contents contains an URL.""" - re_match_urls = re.compile(r"""((?:[a-z][\w-]+:(?:/{1,3}|[a-z0-9%])|www\d{0,3}[.]|[a-z0-9.\-]+[.‌​][a-z]{2,4}/)(?:[^\s()<>]+|(([^\s()<>]+|(([^\s()<>]+)))*))+(?:(([^\s()<>]+|(‌​([^\s()<>]+)))*)|[^\s`!()[]{};:'".,<>?«»“”‘’]))""", re.DOTALL) + re_match_urls = re.compile( + r"""((?:[a-z][\w-]+:(?:/{1,3}|[a-z0-9%])|www\d{0,3}[.]|[a-z0-9.\-]+[.‌​][a-z]{2,4}/)(?:[^\s()<>]+|(([^\s()<>]+|(([^\s()<>]+)))*))+(?:(([^\s()<>]+|(‌​([^\s()<>]+)))*)|[^\s`!()[]{};:'".,<>?«»“”‘’]))""", + re.DOTALL, + ) m = re_match_urls.search(contents) return True if m else False @@ -239,33 +276,33 @@ def is_url(contents): def mangle_url(url): """Mangle URL for links.""" url = url.strip() - if re.match(r'^([a-z0-9-]+\.)+\w{2,4}', url, re.IGNORECASE): - url = 'http://' + url + if re.match(r"^([a-z0-9-]+\.)+\w{2,4}", url, re.IGNORECASE): + url = "http://" + url return url def append_reference_link(edit, view, name, url): r"""Detect if file ends with \n.""" - if view.substr(view.size() - 1) == '\n': - nl = '' + if view.substr(view.size() - 1) == "\n": + nl = "" else: - nl = '\n' + nl = "\n" # Append the new reference link to the end of the file edit_position = view.size() + len(nl) + 1 - view.insert(edit, view.size(), '{0}[{1}]: {2}\n'.format(nl, name, url)) + view.insert(edit, view.size(), "{0}[{1}]: {2}\n".format(nl, name, url)) return sublime.Region(edit_position, edit_position + len(name)) def suggest_default_link_name(name, image): """Suggest default link name in camel case.""" - ret = '' + ret = "" name_segs = name.split() if len(name_segs) > 1: for word in name_segs: ret += word.capitalize() if len(ret) > 30: break - return ('image' if image else '') + ret + return ("image" if image else "") + ret else: return name @@ -283,7 +320,7 @@ def check_for_link(view, link): return None -class ReferenceNewReferenceCommand(MDETextCommand): +class MdeReferenceNewReferenceCommand(MdeTextCommand): """Create a new reference.""" def run(self, edit, image=False): @@ -316,7 +353,7 @@ def run(self, edit, image=False): selection.add_all(edit_regions) -class ReferenceNewInlineLinkCommand(MDETextCommand): +class MdeReferenceNewInlineLinkCommand(MdeTextCommand): """Create a new inline link.""" def run(self, edit, image=False): @@ -326,34 +363,44 @@ def run(self, edit, image=False): link = mangle_url(contents) if is_url(contents) else "" link = link.replace("$", "\\$") if image: - view.run_command("insert_snippet", {"contents": "![${1:$SELECTION}](${2:" + link + "})"}) + view.run_command( + "insert_snippet", {"contents": "![${1:$SELECTION}](${2:" + link + "})"} + ) else: view.run_command("insert_snippet", {"contents": "[${1:$SELECTION}](${2:" + link + "})"}) -class ReferenceNewInlineImage(MDETextCommand): +class MdeReferenceNewInlineImageCommand(MdeTextCommand): """Create a new inline image.""" def run(self, edit): """Run command callback.""" - self.view.run_command("reference_new_inline_link", {"image": True}) + self.view.run_command("mde_reference_new_inline_link", {"image": True}) -class ReferenceNewImage(MDETextCommand): +class MdeReferenceNewImageCommand(MdeTextCommand): """Create a new image.""" def run(self, edit): """Run command callback.""" - self.view.run_command("reference_new_reference", {"image": True}) + self.view.run_command("mde_reference_new_reference", {"image": True}) def get_next_footnote_marker(view): """Get the number of the next footnote.""" refs = getReferences(view) - footnotes = [int(ref[1:]) for ref in refs if view.substr(refs[ref].regions[0])[0] == "^"] + + footnotes = [] + for ref in refs: + if ref[0] == "^": + try: + footnotes.append(int(ref[1:])) + except ValueError: + pass def target_loc(num): return (num - 1) % len(footnotes) + for i in range(len(footnotes)): footnote = footnotes[i] tl = target_loc(footnote) @@ -374,29 +421,29 @@ def target_loc(num): return len(footnotes) + 1 -class ReferenceNewFootnote(MDETextCommand): +class MdeReferenceNewFootnoteCommand(MdeTextCommand): """Create a new footnote.""" def run(self, edit): """Run command callback.""" view = self.view markernum = get_next_footnote_marker(view) - markernum_str = '[^%s]' % markernum + markernum_str = "[^%s]" % markernum for sel in view.sel(): startloc = sel.end() if bool(view.size()): - targetloc = view.find('(\s|$)', startloc).begin() + targetloc = view.find(r"(\s|$)", startloc).begin() else: targetloc = 0 view.insert(edit, targetloc, markernum_str) if len(view.sel()) > 0: view.show(view.size()) - view.insert(edit, view.size(), '\n' + markernum_str + ': ') + view.insert(edit, view.size(), "\n" + markernum_str + ": ") view.sel().clear() view.sel().add(sublime.Region(view.size(), view.size())) -class ReferenceDeleteReference(MDETextCommand): +class MdeReferenceDeleteReferenceCommand(MdeTextCommand): """Delete a reference.""" def run(self, edit): @@ -412,25 +459,38 @@ def run(self, edit): if defname_key in markers: for marker in markers[defname_key].regions: if defname[0] == "^": - edit_regions.append(sublime.Region(marker.begin() - 1, marker.end() + 1)) + edit_regions.append( + sublime.Region(marker.begin() - 1, marker.end() + 1) + ) else: - l = findScopeFrom(view, marker.begin(), marker_begin_scope_name, True) - if l > 0 and view.substr(sublime.Region(l - 1, l)) == "!": - edit_regions.append(sublime.Region(l - 1, l + 1)) + left = findScopeFrom( + view, marker.begin(), marker_begin_scope_name, True + ) + if left > 0 and view.substr(sublime.Region(left - 1, left)) == "!": + edit_regions.append(sublime.Region(left - 1, left + 1)) else: - edit_regions.append(sublime.Region(l, l + 1)) + edit_regions.append(sublime.Region(left, left + 1)) if hasScope(view.scope_name(marker.end()), marker_text_end_scope_name): - if view.substr(sublime.Region(marker.end() + 1, marker.end() + 2)) == '[': + if ( + view.substr(sublime.Region(marker.end() + 1, marker.end() + 2)) + == "[" + ): # [Text][] - r = findScopeFrom(view, marker.end(), marker_end_scope_name, False) - edit_regions.append(sublime.Region(marker.end(), r + 1)) + right = findScopeFrom( + view, marker.end(), marker_end_scope_name, False + ) + edit_regions.append(sublime.Region(marker.end(), right + 1)) else: # [Text] - edit_regions.append(sublime.Region(marker.end(), marker.end() + 1)) + edit_regions.append( + sublime.Region(marker.end(), marker.end() + 1) + ) else: # [Text][name] - r = findScopeFrom(view, marker.begin(), marker_text_end_scope_name, True) - edit_regions.append(sublime.Region(r, marker.end() + 1)) + right = findScopeFrom( + view, marker.begin(), marker_text_end_scope_name, True + ) + edit_regions.append(sublime.Region(right, marker.end() + 1)) if defname_key in refs: for ref in refs[defname_key].regions: edit_regions.append(view.full_line(ref.begin())) @@ -443,10 +503,13 @@ def run(self, edit): def delete_all(index): if index == 0: view.run_command("left_delete") - view.window().show_quick_panel(["Delete the References", "Preview the Changes"], delete_all, sublime.MONOSPACE_FONT) + + view.window().show_quick_panel( + ["Delete the References", "Preview the Changes"], delete_all, sublime.MONOSPACE_FONT + ) -class ReferenceOrganize(MDETextCommand): +class MdeReferenceOrganizeCommand(MdeTextCommand): """Sort and report all references.""" def run(self, edit): @@ -455,7 +518,9 @@ def run(self, edit): # reorder markers = getMarkers(view) - marker_order = sorted(markers.keys(), key=lambda marker: min(markers[marker].regions, key=lambda reg: reg.a).a) + marker_order = sorted( + markers.keys(), key=lambda marker: min(markers[marker].regions, key=lambda reg: reg.a).a + ) marker_order = dict(zip(marker_order, range(0, len(marker_order)))) refs = getReferences(view) @@ -473,7 +538,9 @@ def run(self, edit): sel.add(line_reg) flatfns.sort(key=operator.itemgetter(0)) - flatrefs.sort(key=lambda x: marker_order[x[0].lower()] if x[0].lower() in marker_order else 9999) + flatrefs.sort( + key=lambda x: marker_order[x[0].lower()] if x[0].lower() in marker_order else 9999 + ) view.run_command("left_delete") if view.size() >= 2 and view.substr(sublime.Region(view.size() - 2, view.size())) == "\n\n": @@ -495,7 +562,7 @@ def run(self, edit): output = "" for name in refs: - if name[0] == '^': + if name[0] == "^": continue n_links = len(refs[name].regions) if n_links > 1: @@ -516,7 +583,11 @@ def run(self, edit): # view.run_command("left_delete") for name in conflicts: - output += "%s has conflict values: %s with %s\n" % (refs[name].label, unique_links[name], ", ".join(conflicts[name])) + output += "%s has conflict values: %s with %s\n" % ( + refs[name].label, + unique_links[name], + ", ".join(conflicts[name]), + ) # report missing refs = getReferences(view) @@ -526,14 +597,20 @@ def run(self, edit): if ref not in marker_order: missings.append(refs[ref].label) if len(missings) > 0: - output += "Error: Definition [%s] %s no reference\n" % (", ".join(missings), "have" if len(missings) > 1 else "has") + output += "Error: Definition [%s] %s no reference\n" % ( + ", ".join(missings), + "have" if len(missings) > 1 else "has", + ) missings = [] for marker in markers: if marker not in lower_refs: missings.append(markers[marker].label) if len(missings) > 0: - output += "Error: [%s] %s no definition\n" % (", ".join(missings), "have" if len(missings) > 1 else "has") + output += "Error: [%s] %s no definition\n" % ( + ", ".join(missings), + "have" if len(missings) > 1 else "has", + ) # sel.clear() if len(output) == 0: @@ -549,16 +626,22 @@ def get_times_string(n): else: return "%i times" % n - output += "\n".join(('[%s] is referenced %s' % (markers[m].label, get_times_string(len(markers[m].regions)))) for m in markers) + output += "\n".join( + ( + "[%s] is referenced %s" + % (markers[m].label, get_times_string(len(markers[m].regions))) + ) + for m in markers + ) window = view.window() output_panel = window.create_output_panel("mde") - output_panel.run_command('erase_view') - output_panel.run_command('append', {'characters': output}) + output_panel.run_command("erase_view") + output_panel.run_command("append", {"characters": output}) window.run_command("show_panel", {"panel": "output.mde"}) -class GatherMissingLinkMarkersCommand(MDETextCommand): +class MdeGatherMissingLinkMarkersCommand(MdeTextCommand): """Gather all missing references and creates them.""" def run(self, edit): @@ -572,15 +655,15 @@ def run(self, edit): missings.append(marker) if len(missings): # Remove all whitespace at the end of the file - whitespace_at_end = view.find(r'\s*\z', 0) + whitespace_at_end = view.find(r"\s*\z", 0) view.replace(edit, whitespace_at_end, "\n") # If there is not already a reference list at the end, insert a new line at the end - if not view.find(r'\n\s*\[[^\]]*\]:.*\s*\z', 0): + if not view.find(r"\n\s*\[[^\]]*\]:.*\s*\z", 0): view.insert(edit, view.size(), "\n") for link in missings: - view.insert(edit, view.size(), '[%s]: \n' % link) + view.insert(edit, view.size(), "[%s]: \n" % link) def convert2ref(view, edit, link_span, name, omit_name=False): @@ -588,31 +671,31 @@ def convert2ref(view, edit, link_span, name, omit_name=False): view.sel().clear() link = view.substr(sublime.Region(link_span.a + 1, link_span.b - 1)) if omit_name: - view.replace(edit, link_span, '[]') + view.replace(edit, link_span, "[]") link_span = sublime.Region(link_span.a + 1, link_span.a + 1) offset = len(link) else: - view.replace(edit, link_span, '[%s]' % name) + view.replace(edit, link_span, "[%s]" % name) link_span = sublime.Region(link_span.a + 1, link_span.a + 1 + len(name)) offset = len(link) - len(name) view.sel().add(link_span) view.show_at_center(link_span) _viewsize = view.size() - view.insert(edit, _viewsize, '[%s]: %s\n' % (name, link)) + view.insert(edit, _viewsize, "[%s]: %s\n" % (name, link)) reference_span = sublime.Region(_viewsize + 1, _viewsize + 1 + len(name)) view.sel().add(reference_span) return offset -class ConvertInlineLinkToReferenceCommand(MDETextCommand): +class MdeConvertInlineLinkToReferenceCommand(MdeTextCommand): """Convert an inline link to reference.""" def is_visible(self): """Return True if cursor is on a marker or reference.""" for sel in self.view.sel(): scope_name = self.view.scope_name(sel.b) - if hasScope(scope_name, 'meta.link.inline.markdown'): + if hasScope(scope_name, "meta.link.inline.markdown"): return True return False @@ -622,21 +705,23 @@ def run(self, edit, name=None): pattern = r"\[([^\]]+)\]\((?!#)([^\)]+)\)" # Remove all whitespace at the end of the file - whitespace_at_end = view.find(r'\s*\z', 0) + whitespace_at_end = view.find(r"\s*\z", 0) view.replace(edit, whitespace_at_end, "\n") # If there is not already a reference list at the end, insert a new line at the end - if not view.find(r'\n\s*\[[^\]]*\]:.*\s*\z', 0): + if not view.find(r"\n\s*\[[^\]]*\]:.*\s*\z", 0): view.insert(edit, view.size(), "\n") link_spans = [] for sel in view.sel(): scope_name = view.scope_name(sel.b) - if not hasScope(scope_name, 'meta.link.inline.markdown'): + if not hasScope(scope_name, "meta.link.inline.markdown"): continue start = findScopeFrom(view, sel.b, marker_begin_scope_name, backwards=True) - end = findScopeFrom(view, sel.b, 'punctuation.definition.metadata.markdown', char=')') + 1 + end = ( + findScopeFrom(view, sel.b, "punctuation.definition.metadata.markdown", char=")") + 1 + ) text = view.substr(sublime.Region(start, end)) m = re.match(pattern, text) if m is None: @@ -651,7 +736,7 @@ def run(self, edit, name=None): # If link already exists, reuse existing reference suggested_name = check_for_link(view, link) if suggested_name is None: - is_image = view.substr(start - 1) == '!' if start > 0 else False + is_image = view.substr(start - 1) == "!" if start > 0 else False suggested_name = suggest_default_link_name(text, is_image) _name = name if name is not None else suggested_name @@ -663,7 +748,7 @@ def run(self, edit, name=None): offset -= convert2ref(view, edit, _link_span, link_span[1], link_span[2]) -class ConvertInlineLinksToReferencesCommand(MDETextCommand): +class MdeConvertInlineLinksToReferencesCommand(MdeTextCommand): """Convert inline links to references.""" def run(self, edit): @@ -676,4 +761,128 @@ def run(self, edit): _sel.append(sel) view.sel().clear() view.sel().add_all(view.find_all(pattern)) - view.run_command('convert_inline_link_to_reference') + view.run_command("mde_convert_inline_link_to_reference") + + +class MdeAddNumberedReferenceDefinitionCommand(MdeTextCommand): + """ + The `mde_add_numbered_reference_definition` command adds a new line with a numbered reference + definition if the current line's one contains a label. Otherwise the current line is deleted. + + The added reference uses the next bigger number which does not yet exist in the document. + + The command works for unnamed, named definitions as well as for footnotes. + + ```markdown + [^1]: footnote + [1]: unnamed_reference + [name1]: named_reference + ``` + + **Note:** + + Implementation uses regexp functions as Markdown syntax doesn't scope reference definitions atm. + A future change might make use of `view.find_by_selector("...")` to create the list of existing + references. + """ + + REFERENCE_DEFINITION_PATTERN = r"^([ \t]{0,3})\[(.*?)(\d+)\]:[ \t]*(\S)?" + + def run(self, edit): + view = self.view + pattern = re.compile(self.REFERENCE_DEFINITION_PATTERN) + + refs = {} + + # find all existing reference definitions and group them by name + for ref in view.find_all(self.REFERENCE_DEFINITION_PATTERN): + _, name, num, _ = pattern.search(view.substr(ref)).groups() + refs.setdefault(name, set()).add(int(num)) + + for sel in view.sel(): + line = view.line(sel) + match = pattern.search(view.substr(line)) + if not match: + continue + + indent, name, num, label = match.groups() + if label: + # calculate next none-existing reference number + num = int(num) + while num in refs.get(name, {}): + num += 1 + view.insert(edit, sel.begin(), "\n%s[%s%d]: " % (indent, name, num)) + else: + view.erase(edit, line) + + +def shorten(string, n): + return string if len(string) <= n else string[: n - 1] + "…" + + +if hasattr(sublime, "KIND_ID_MARKUP"): + + class MdeReferenceCompletionsProvider(MdeViewEventListener): + KIND_REFERENCE = (sublime.KIND_ID_MARKUP, "R", "Ref") + + re_reflinks = re.compile( + r"^\[(?P[^\^][^\]]*)\]:[ \t]+(?P\S*)(?:[ \t]+(?P.*))?$", + re.MULTILINE, + ) + + def on_query_completions(self, prefix, locations): + if not self.view.match_selector( + locations[0], + "text.html.markdown meta.link.reference" + " (constant.other.reference.link | punctuation.definition.constant)", + ): + return None + + completions = [] + for ref in self.view.find_by_selector("meta.link.reference.def"): + match = self.re_reflinks.match(self.view.substr(ref)) + if not match: + continue + completions.append( + sublime.CompletionItem( + trigger=match.group("id"), + completion=match.group("id"), + completion_format=sublime.COMPLETION_FORMAT_TEXT, + kind=self.KIND_REFERENCE, + annotation=shorten((match.group("link") or "No link"), 30), + details=(match.group("desc") or "No title").strip(" \t\v\f\r\n'\""), + ) + ) + return sublime.CompletionList( + completions, + sublime.INHIBIT_WORD_COMPLETIONS | sublime.INHIBIT_EXPLICIT_COMPLETIONS, + ) + + +else: + + class MdeReferenceCompletionsProvider(MdeViewEventListener): + re_reflinks = re.compile( + r"^\[(?P[^\^][^\]]*)\]:[ \t]+(?P\S*)(?:[ \t]+(?P.*))?$", + re.MULTILINE, + ) + + def on_query_completions(self, prefix, locations): + if not self.view.match_selector( + locations[0], + "text.html.markdown meta.link.reference" + " (constant.other.reference.link | punctuation.definition.constant)", + ): + return None + + completions = [] + for ref in self.view.find_by_selector("meta.link.reference.def"): + match = self.re_reflinks.match(self.view.substr(ref)) + if not match: + continue + completions.append(match.group("id")) + + return [ + completions, + sublime.INHIBIT_WORD_COMPLETIONS | sublime.INHIBIT_EXPLICIT_COMPLETIONS, + ] diff --git a/plugins/view.py b/plugins/view.py new file mode 100644 index 00000000..109be4e9 --- /dev/null +++ b/plugins/view.py @@ -0,0 +1,109 @@ +import re +import sublime +import sublime_plugin + + +def view_is_markdown(view): + try: + return view.match_selector(view.sel()[0].begin(), "text.html.markdown") + except IndexError: + return False + + +def syntax_specific_settings_file(view): + if isinstance(view, sublime.View): + syntax = view.settings().get("syntax") + if syntax: + return re.sub(r".*/(.+)\.(sublime-syntax|tmLanguage)", r"\1.sublime-settings", syntax) + return None + + +class MdeTextCommand(sublime_plugin.TextCommand): + def is_enabled(self): + return view_is_markdown(self.view) + + def is_visible(self): + return view_is_markdown(self.view) + + +class MdeReplaceSelectedCommand(sublime_plugin.TextCommand): + def run(self, edit, **args): + for region in self.view.sel(): + self.view.replace(edit, region, args["text"]) + + +class MdeViewEventListener(sublime_plugin.ViewEventListener): + @classmethod + def is_applicable(cls, settings): + try: + return "Markdown" in settings.get("syntax") + except (AttributeError, TypeError): + return False + + @classmethod + def applies_to_primary_view_only(cls): + return False + + +class MdeToggleCenteredLineCommand(MdeTextCommand): + """ + The `mde_toggle_centered_line` command temporarily enables/disables line + centering of the current view. + + To permanently enable or disable it, please tweak one of ST's user preferences files. + + - all markdown files: Preferences.sublime-settings + - distraction free mode: Distraction Free.sublime-settings + - syntax specific: [syntax name].sublime-settings + - project specific: [Project].sublime-project + + ```json + { + // ... + "settings": { + "mde.keep_centered": true + } + } + ``` + + The setting is + + - enabled by default in `Distraction Free.sublime-settings` + - disabled by default in `Preferences.sublime-settings` + """ + + def run(self, edit, **args): + settings_file = syntax_specific_settings_file(self.view) or "Markdown.sublime-settings" + syntax_settings = sublime.load_settings(settings_file) + is_centered_by_syntax = syntax_settings.get("mde.keep_centered", False) + + settings = self.view.settings() + want_centered = not settings.get("mde.keep_centered", False) + if want_centered != is_centered_by_syntax: + settings.set("mde.keep_centered", want_centered) + else: + settings.erase("mde.keep_centered") + + +class MdeCenteredLineKeeper(MdeViewEventListener): + """ + This class keeps caret in vertical center position. + These features can be enabled/disabled via settings files. + """ + + current_line = -1 + + def on_modified(self): + sel = self.view.sel() + if sel and len(sel) != 1: + return + + settings = self.view.settings() + if not settings.get("mde.keep_centered", False): + return + + pt = sel[0].begin() + current_line, _ = self.view.rowcol(pt) + if self.current_line != current_line: + self.current_line = current_line + self.view.show_at_center(pt) diff --git a/plugins/wiki_page.py b/plugins/wiki_page.py new file mode 100644 index 00000000..fc6cfc32 --- /dev/null +++ b/plugins/wiki_page.py @@ -0,0 +1,360 @@ +import os +import re +import string +import sys + +import sublime + +from datetime import date + +from .logging import logger +from .view import MdeTextCommand + +DEFAULT_DATE_FORMAT = "%Y-%m-%d" +DEFAULT_HOME_PAGE = "HomePage" +DEFAULT_MARKDOWN_EXTENSION = ".md" +PAGE_REF_FORMAT = "[[%s]]" + + +class MdeListBackLinksCommand(MdeTextCommand): + def run(self, edit): + wiki_page = WikiPage(self.view) + + file_list = wiki_page.find_files_with_ref() + wiki_page.select_backlink(file_list) + + +class MdeMakePageReferenceCommand(MdeTextCommand): + def is_visible(self): + """Return True if is on a wiki page reference.""" + for sel in self.view.sel(): + if not self.view.match_selector(sel.end(), "meta.link.wiki.markdown"): + return False + return True + + def run(self, edit): + wiki_page = WikiPage(self.view) + + word_region = wiki_page.select_word_at_cursor() + file_list = wiki_page.find_matching_files(word_region) + + wiki_page.make_page_reference(edit, word_region) + + if len(file_list) > 1: + wiki_page.show_quick_list(file_list) + + +class MdeOpenHomePageCommand(MdeTextCommand): + def run(self, edit): + home_page = self.view.settings().get("mde.wikilinks.homepage", DEFAULT_HOME_PAGE) + + wiki_page = WikiPage(self.view) + wiki_page.select_page(home_page) + + +class MdeOpenJournalCommand(MdeTextCommand): + def run(self, edit): + today = date.today() + date_format = self.view.settings().get("mde.journal.dateformat", DEFAULT_DATE_FORMAT) + name = today.strftime(date_format) + + wiki_page = WikiPage(self.view) + wiki_page.select_page(name) + + +class MdeOpenPageCommand(MdeTextCommand): + def is_visible(self): + """Return True if caret is on a wiki page reference.""" + for sel in self.view.sel(): + if not self.view.match_selector(sel.end(), "meta.link.wiki.markdown"): + return False + return True + + def run(self, edit): + wiki_page = WikiPage(self.view) + + sel_region = self.get_selected() + if sel_region: + wiki_page.select_word_at_cursor() + + region = sublime.Region(sel_region.begin(), sel_region.begin()) + file_list = wiki_page.find_matching_files(region) + + if len(file_list) > 1: + wiki_page.show_quick_list(file_list) + else: + name = wiki_page.identify_page_at_cursor() + wiki_page.select_page(name) + + def get_selected(self): + selection = self.view.sel() + for region in selection: + return region + + return None + + +class MdePrepareFromTemplateCommand(MdeTextCommand): + + DEFAULT_PAGE_TEMPLATE = "templates/PageTemplate.md" + PRESET_TEMPLATE_TEXT = "# $title\n\n" + + def run(self, edit, **args): + """Prepare a new page content from a named template. + + :Example: + + view.run_command('mde_prepare_from_template', { + 'title': pagename, + 'template': 'default_page' + }) + + :param self: This command instance + :param edit: The sublime edit instance + :param args: The command arguments including 'title' and 'template' + """ + + template_name = args["template"] + logger.info("Creating new page from template: ", template_name) + + text = self.generate_from_template(template_name, args) + self.view.insert(edit, 0, text) + + def generate_from_template(self, template_name, args): + """Generate the text using the template""" + + template_text = self.retrieve_template_text(template_name) + template = string.Template(template_text) + return template.substitute(args) + + def retrieve_template_text(self, template_name): + """Retrieve the template text. + + The setting 'mde.wikilinks.templates' may be configured with a filename for + the template. This file (if it exists) will be loaded otherwise the preset + template will be used + """ + + template = self.view.settings().get("mde.wikilinks.templates", self.DEFAULT_PAGE_TEMPLATE) + + if not os.path.isfile(template): + current_file = self.view.file_name() + current_dir = os.path.dirname(current_file) + template = os.path.join(current_dir, template) + + if os.path.isfile(template): + logger.debug("Using template:", template) + try: + with open(template, "rt") as f: + return f.read() + except OSError: + logger.debug("Unable to read template:", sys.exc_info()[0]) + + # Unable to load template so using preset template + logger.warning("Template:", template, "not found. Using preset.") + return self.PRESET_TEMPLATE_TEXT + + +class WikiPage: + def __init__(self, view): + self.view = view + + def identify_page_at_cursor(self): + for region in self.view.sel(): + text_on_cursor = None + + pos = region.begin() + scope_region = self.view.extract_scope(pos) + if not scope_region.empty(): + text_on_cursor = self.view.substr(scope_region) + return text_on_cursor.strip(string.punctuation) + + return None + + def select_page(self, pagename): + logger.debug("Open page: %s" % (pagename)) + + if pagename: + self.file_list = self.find_files_with_name(pagename) + + if len(self.file_list) > 1: + self.view.window().show_quick_panel(self.file_list, self.open_selected_file) + elif len(self.file_list) == 1: + self.open_selected_file(0) + else: + self.open_new_file(pagename) + + def find_files_with_name(self, pagename): + pagename = pagename.replace("\\", os.sep).replace(os.sep + os.sep, os.sep).strip() + + self.current_file = self.view.file_name() + self.current_dir = os.path.dirname(self.current_file) + logger.debug("Locating page '%s' in: %s" % (pagename, self.current_dir)) + + markdown_extension = self.view.settings().get( + "mde.wikilinks.markdown_extension", DEFAULT_MARKDOWN_EXTENSION + ) + + # Optionally strip extension... + if pagename.endswith(markdown_extension): + search_pattern = "^%s$" % pagename + else: + search_pattern = "^%s%s$" % (pagename, markdown_extension) + + # Scan directory tree for files that match the pagename... + results = [] + for dirname, _, files in self.list_dir_tree(self.current_dir): + for file in files: + if re.search(search_pattern, file): + filename = os.path.join(dirname, file) + results.append([self.extract_page_name(filename), filename]) + + return results + + def find_files_with_ref(self): + self.current_file = self.view.file_name() + self.current_dir, current_base = os.path.split(self.current_file) + self.current_name, _ = os.path.splitext(current_base) + + markdown_extension = self.view.settings().get( + "mde.wikilinks.markdown_extension", DEFAULT_MARKDOWN_EXTENSION + ) + + results = [] + for dirname, _, files in self.list_dir_tree(self.current_dir): + for file in files: + page_name, extension = os.path.splitext(file) + filename = os.path.join(dirname, file) + if extension == markdown_extension and self.contains_ref( + filename, self.current_name + ): + results.append([page_name, filename]) + + return results + + def contains_ref(self, filename, page_name): + link_text = PAGE_REF_FORMAT % page_name + + try: + if link_text in open(filename).read(): + return True + except OSError: + pass + + return False + + def select_backlink(self, file_list): + if file_list: + self.file_list = file_list + self.view.window().show_quick_panel(self.file_list, self.open_selected_file) + else: + msg = "No pages reference this page" + logger.error(msg) + self.view.window().status_message(msg) + + def open_new_file(self, pagename): + current_syntax = self.view.settings().get("syntax") + current_file = self.view.file_name() + current_dir = os.path.dirname(current_file) + + markdown_extension = self.view.settings().get( + "mde.wikilinks.markdown_extension", DEFAULT_MARKDOWN_EXTENSION + ) + + filename = os.path.join(current_dir, pagename + markdown_extension) + + new_view = self.view.window().new_file() + new_view.retarget(filename) + new_view.run_command( + "mde_prepare_from_template", {"title": pagename, "template": "default_page"} + ) + logger.debug("Current syntax: %s", current_syntax) + new_view.set_syntax_file(current_syntax) + + # Create but don't save page + # new_view.run_command('save') + + def open_selected_file(self, selected_index): + if selected_index != -1: + _, file = self.file_list[selected_index] + + logger.debug("Opening file '%s'", file) + self.view.window().open_file(file) + + def extract_page_name(self, filename): + _, base_name = os.path.split(filename) + page_name, _ = os.path.splitext(base_name) + + return page_name + + def list_dir_tree(self, directory): + for dir, dirnames, files in os.walk(directory): + dirnames[:] = [dirname for dirname in dirnames] + yield dir, dirnames, files + + def select_word_at_cursor(self): + word_region = None + + selection = self.view.sel() + for region in selection: + word_region = self.view.word(region) + if not word_region.empty(): + selection.clear() + selection.add(word_region) + return word_region + + return word_region + + def show_quick_list(self, file_list): + self.file_list = file_list + + window = self.view.window() + window.show_quick_panel(file_list, self.replace_selection_with_pagename) + + def replace_selection_with_pagename(self, selected_index): + if selected_index != -1: + page_name, file = self.file_list[selected_index] + + logger.debug("Using selected page '%s'", page_name) + self.view.run_command("mde_replace_selected", {"text": page_name}) + + def find_matching_files(self, word_region): + word = None if word_region.empty() else self.view.substr(word_region) + + current_file = self.view.file_name() + current_dir, current_base = os.path.split(current_file) + logger.debug("Finding matching files for %s in %s", word, current_dir) + + markdown_extension = self.view.settings().get( + "mde.wikilinks.markdown_extension", DEFAULT_MARKDOWN_EXTENSION + ) + + # Optionally strip extension... + if word is not None and word.endswith(markdown_extension): + word = word[: -len(markdown_extension)] + + # Scan directory tree for potential filenames that contain the word... + results = [] + for dirname, _, files in self.list_dir_tree(current_dir): + for file in files: + page_name, extension = os.path.splitext(file) + filename = os.path.join(dirname, file) + + if extension == markdown_extension and (not word or word in page_name): + results.append([page_name, filename]) + + return results + + def make_page_reference(self, edit, region): + logger.debug("Make page reference %s", region) + + begin = region.begin() + end = region.end() + + self.view.insert(edit, end, "]]") + self.view.insert(edit, begin, "[[") + + if region.empty(): + selection = self.view.sel() + selection.clear() + selection.add(sublime.Region(begin + 2, end + 2)) diff --git a/prepare_from_template.py b/prepare_from_template.py deleted file mode 100644 index 32856fa2..00000000 --- a/prepare_from_template.py +++ /dev/null @@ -1,67 +0,0 @@ -import sublime, sublime_plugin - -import sys -import os.path - -from string import Template - - -DEFAULT_PAGE_TEMPLATE = "templates/PageTemplate.md" -PRESET_TEMPLATE_TEXT = "# $title\n\n" - -class PrepareFromTemplateCommand(sublime_plugin.TextCommand): - def run(self, edit, **args): - """Prepare a new page content from a named template triggered from run command 'prepare_from_template'. - - :Example: - - view.run_command('prepare_from_template', { - 'title': pagename, - 'template': 'default_page' - }) - - :param self: This command instance - :param edit: The sublime edit instance - :param args: The command arguments including 'title' and 'template' - """ - - print("Running PrepareFromTemplateCommand") - template_name = args['template'] - print("Creating new page from template: ", template_name) - - text = self.generate_from_template(template_name, args) - self.view.insert(edit, 0, text) - - def generate_from_template(self, template_name, args): - """Generate the text using the template""" - - template_text = self.retrieve_template_text(template_name) - template = Template(template_text) - return template.substitute(args) - - def retrieve_template_text(self, template_name): - """Retrieve the template text. - - The setting 'mde.wikilinks.templates' may be configured with a filename for - the template. This file (if it exists) will be loaded otherwise the preset - template will be used - """ - - template = self.view.settings().get("mde.wikilinks.templates", DEFAULT_PAGE_TEMPLATE) - - if not os.path.isfile(template): - current_file = self.view.file_name() - current_dir = os.path.dirname(current_file) - template = os.path.join(current_dir, template) - - if os.path.isfile(template): - print("Using template:", template) - try: - with open(template, 'rt') as f: - return f.read() - except: - print("Unable to read template:", sys.exc_info()[0]) - - # Unable to load template so using preset template - print("Template:", template, "not found. Using preset.") - return PRESET_TEMPLATE_TEXT diff --git a/pyproject.toml b/pyproject.toml new file mode 100644 index 00000000..857ecb73 --- /dev/null +++ b/pyproject.toml @@ -0,0 +1,14 @@ +# Configuration for Black. + +[tool.black] +line-length = 100 +target-version = ['py38'] +exclude = ''' + \.git + | \.github + | \.mypy_cache + | \.pytest_cache + | \.venv + | plugin\.py + | tests +''' diff --git a/replace_selected_command.py b/replace_selected_command.py deleted file mode 100644 index 94a2a527..00000000 --- a/replace_selected_command.py +++ /dev/null @@ -1,12 +0,0 @@ -import sublime, sublime_plugin -import os, string - -try: - from MarkdownEditing.mdeutils import * -except ImportError: - from mdeutils import * - -class ReplaceSelectedCommand(MDETextCommand): - def run(self, edit, **args): - for region in self.view.sel(): - self.view.replace(edit, region, args['text']) diff --git a/samples/Fenced Code Blocks.md b/samples/Fenced Code Blocks.md deleted file mode 100644 index 4997a206..00000000 --- a/samples/Fenced Code Blocks.md +++ /dev/null @@ -1,25 +0,0 @@ -```html - - - - Hi! - - -

Hello, world!

- - -``` - -~~~~~~java -public class HelloWorld { - public static void main(String[] args) { - System.out.println("Hello, world!"); - } -} -~~~~~~ - -```sql -SELECT "Hello, world!" FROM DUMMY -- Hello, world! -SELECT "Hello, world!" FROM DUMMY -- Hello, world! -``` diff --git a/samples/GFM.md b/samples/GFM.md deleted file mode 100644 index d5063fe7..00000000 --- a/samples/GFM.md +++ /dev/null @@ -1,35 +0,0 @@ -# Sample Markdown - -Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod. - -## Text basics - -This is *italic* and this is **bold**. Another _italic_ and another __bold__. - -> __Here is some quotation__. 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. - -## Links - -This is an [example inline link](http://example.com/) and [another one with a title](http://example.com/ "Hello, world"). And [another][someref] one. - -## Code - -This is inline code: `some code here`. - - - -```java -public class HelloWorld { - public static void main(String[] args) { - System.out.println("Hello, world!"); - } -} -``` - -[someref]: http://example.com "rich web apps" -[MarkdownREF]: http://daringfireball.net/projects/markdown/basics -[gfm]: http://github.github.com/github-flavored-markdown/ diff --git a/samples/README.md b/samples/README.md deleted file mode 100644 index 4f42b157..00000000 --- a/samples/README.md +++ /dev/null @@ -1,4 +0,0 @@ -Markdown files in this folder can be used for tasks like: - -* Taking screenshots after a syntax highlighting update in the plugin, -* Checking if the plugin works legitimately in general. diff --git a/schemes/Mariana.sublime-color-scheme b/schemes/Mariana.sublime-color-scheme new file mode 100644 index 00000000..d438c3f1 --- /dev/null +++ b/schemes/Mariana.sublime-color-scheme @@ -0,0 +1,145 @@ +// This patch for Mariana.sublime-color-scheme adds some Markdown specific color definitions +// while making use of well defined colors for code blocks. +{ + "variables": { + "line_break": "hsl(210, 15%, 20%)", + "raw_fg": "hsl(210, 10%, 60%)", + "raw_bg": "hsl(210, 15%, 20%)" + }, + "rules": [ + + // Basic Formattings + { + "name": "Bold Content", + "scope": "text.html.markdown markup.bold - punctuation.definition.bold", + "font_style": "bold" + }, + { + "name": "Bold Punctuation", + "scope": "text.html.markdown punctuation.definition.bold", + "font_style": "" + }, + { + "name": "Italic Content", + "scope": "text.html.markdown markup.italic - punctuation.definition.italic", + "font_style": "italic" + }, + { + "name": "Italic Punctuation", + "scope": "text.html.markdown punctuation.definition.italic", + "font_style": "" + }, + { + "name": "Bold Italic Content", + "scope": "text.html.markdown markup.bold markup.italic - punctuation.definition.bold - punctuation.definition.italic, text.html.markdown markup.bold_italic - punctuation.definition.bold", + "font_style": "bold italic" + }, + { + "name": "Underlined Content", + "scope": "text.html.markdown markup.underline", + "font_style": "underline" + }, + { + "name": "Bold Underlined Content", + "scope": "text.html.markdown & markup.bold & markup.underline - punctuation.definition.bold", + "font_style": "bold underline" + }, + { + "name": "Italic Underlined Content", + "scope": "text.html.markdown & markup.italic & markup.underline - punctuation.definition.italic", + "font_style": "italic underline" + }, + { + "name": "Bold Italic Underlined Content", + "scope": "text.html.markdown & markup.bold & markup.italic & markup.underline - punctuation.definition.bold - punctuation.definition.italic", + "font_style": "bold underline" + }, + { + "name": "Striked Content", + "scope": "text.html.markdown markup.strikethrough", + "foreground": "var(grey)", + "font_style": "" + }, + { + "name": "Striked References", + "scope": "text.html.markdown markup.strikethrough & (punctuation.definition.constant | punctuation.definition.image | punctuation.definition.link | punctuation.definition.metadata)", + "foreground": "var(grey)", + "font_style": "" + }, + { + "name": "Striked Strings", + "scope": "text.html.markdown markup.strikethrough string", + "foreground": "var(grey)", + "font_style": "" + }, + { + "name": "Markdown: Hard Line Breaks", + "scope": "text.html.markdown punctuation.definition.hard-line-break", + "background": "var(line_break)" + }, + + // Block Quotes + { + "name": "Block Quotes", + "scope": "text.html.markdown markup.quote punctuation.definition.blockquote, text.html.markdown markup.quote punctuation.definition.quote", + "foreground": "var(blue2)", + "background": "var(blue2)" + }, + + // Code Blocks + { + "name": "Inline Code Block", + "scope": "text.html.markdown markup.raw.inline", + "foreground": "var(raw_fg)", + "background": "var(raw_bg)" + }, + { + "name": "Inline Code Block Punctuation", + "scope": "text.html.markdown markup.raw.inline punctuation.definition.raw", + "foreground": "var(raw_bg)", + "background": "var(raw_bg)" + }, + { + "name": "Raw Code Block", + "scope": "text.html.markdown markup.raw, text.html.markdown meta.code-fence", + "foreground": "var(raw_fg)", + "background": "var(raw_bg)" + }, + + // Inline References + { + "name": "Inline Link URL", + "scope": "text.html.markdown meta.link.inline markup.underline.link", + "foreground": "var(pink)" + }, + + // Keyboard Shortcuts + { + "name": "Keyboard Shortcut Background", + "scope": "text.html.markdown markup.kbd", + "background": "var(raw_bg)" + }, + { + "name": "Keyboard Shortcut Tags", + "scope": "text.html.markdown markup.kbd entity.name.tag, text.html.markdown markup.kbd punctuation.definition.tag", + "foreground": "var(raw_fg)" + }, + { + "name": "Keyboard Shortcut Content", + "scope": "text.html.markdow markup.kbd.content", + "foreground": "var(blue)" + }, + + // Tables + { + "name": "Table Separators / Lines", + "scope": "text.html.markdown meta.table.header-separator punctuation.section, text.html.markdown punctuation.section.table-header, text.html.markdown punctuation.separator.table-cell", + "foreground": "var(grey)" + }, + { + "name": "Table Cell Content Alignment Operator", + "scope": "text.html.markdown meta.table.header-separator punctuation.definition", + "foreground": "var(pink)" + } + ] +} diff --git a/schemes/MarkdownEditor-ArcDark.sublime-color-scheme b/schemes/MarkdownEditor-ArcDark.sublime-color-scheme new file mode 100644 index 00000000..a5194836 --- /dev/null +++ b/schemes/MarkdownEditor-ArcDark.sublime-color-scheme @@ -0,0 +1,555 @@ +{ + "name": "MarkdownEditing", + "author": "Unknown", + "variables": { + + // Critic Markup + + "critic_inserted_fg": "#46a524", + "critic_inserted_bg": "color(var(critic_inserted_fg) a(7%))", + "critic_inserted_punct": "color(var(critic_inserted_fg) a(40%))", + + "critic_deleted_fg": "#f92672", + "critic_deleted_bg": "color(var(critic_deleted_fg) a(7%))", + "critic_deleted_punct": "color(var(critic_deleted_fg) a(40%))", + + "critic_comment_fg": "#7f7f7f", + "critic_comment_bg": "color(var(critic_comment_fg) a(7%))", + "critic_comment_punct": "color(var(critic_comment_fg) a(40%))", + + "critic_highlight_fg": "#6d98cf", + "critic_highlight_bg": "color(var(critic_highlight_fg) a(7%))", + "critic_highlight_punct": "color(var(critic_highlight_fg) a(40%))", + + "critic_substitution_fg": "#ddb700", + "critic_substitution_bg": "color(var(critic_substitution_fg) a(7%))", + "critic_substitution_punct": "color(var(critic_substitution_fg) a(80%))", + + // Diff Markup + + "diff_header_range_fg": "#bcbcbc", + "diff_header_range_bg": "#150d0a", + "diff_header_from_fg": "var(diff_header_range_fg)", + "diff_header_from_bg": "#002222", + "diff_header_to_fg": "var(diff_header_range_fg)", + "diff_header_to_bg": "#220022", + "diff_deleted_fg": "#F92672", + "diff_deleted_bg": "color(var(diff_deleted_fg) a(7%))", + "diff_inserted_fg": "#A6E22E", + "diff_inserted_bg": "color(var(diff_inserted_fg) a(7%))", + "diff_changed_fg": "#967EFB", + "diff_changed_bg": "color(var(diff_changed_fg) a(7%))", + "diff_ignored_fg": "#565656", + "diff_ignored_bg": "color(var(diff_ignored_fg) a(7%))", + "diff_untracked_fg": "#565656", + "diff_untracked_bg": "color(var(diff_untracked_fg) a(7%))", + + // Linter Markup + + "info_fg": "#61862F", + "info_bg": "transparent", + "error_fg": "#D02000", + "error_bg": "transparent", + "warning_fg": "#DDB700", + "warning_bg": "transparent" + }, + "globals": + { + "foreground": "#ffffff", + "background": "#383C4A", + "caret": "#F8F8F0", + "invisibles": "#31333D", + "line_highlight": "#2d3036", + "selection": "#484A58", + "inactive_selection": "#4a2c1a", + "find_highlight_foreground": "#ffffff", + "find_highlight": "#00186d" + }, + "rules": + [ + { + "name": "Comments", + "scope": "comment, comment punctuation", + "foreground": "#585964" + }, + { + "name": "Comments: Preprocessor", + "scope": "comment.block.preprocessor", + "foreground": "#C77E77" + }, + { + "name": "Invalid - Deprecated", + "scope": "invalid.deprecated", + "foreground": "#F8F8F0", + "background": "#AE81FF", + "font_style": "italic underline" + }, + { + "name": "Invalid - Illegal", + "scope": "invalid.illegal", + "foreground": "#060d31" + }, + { + "name": "Keywords", + "scope": "keyword, storage", + "foreground": "#9e79d0" + }, + { + "name": "Operators", + "scope": "keyword.operator", + "foreground": "#9d9036" + }, + { + "name": "Types", + "scope": "keyword.declaration, storage.type, support.type", + "foreground": "#98ff46" + }, + { + "name": "Functions", + "scope": "entity.name.function, support.function, entity", + "foreground": "#9e79d0" + }, + { + "name": "Classes", + "scope": "entity.name.type, entity.other.inherited-class, support.class", + "foreground": "#C77E77" + }, + { + "name": "Exceptions", + "scope": "entity.name.exception", + "foreground": "#06cdcd" + }, + { + "name": "Sections", + "scope": "entity.name.section", + "foreground": "#C77E77", + "font_style": "bold" + }, + { + "name": "Numbers", + "scope": "constant.numeric, constant", + "foreground": "#BBCF54" + }, + { + "name": "Punctuation", + "scope": "punctuation", + "foreground": "#ffffff" + }, + { + "name": "Strings", + "scope": "string, constant.character", + "foreground": "#4398f0" + }, + { + "name": "Strings: Punctuation", + "scope": "string punctuation", + "foreground": "#1965b3" + }, + { + "name": "Strings: Escape Sequences", + "scope": "constant.character.escape", + "font_style": "bold" + }, + { + "name": "Strings: Symbols", + "scope": "constant.other.symbol", + "background": "#17002a", + "font_style": "bold" + }, + { + "name": "Embedded Source", + "scope": "string source, text source", + "foreground": "#bcbcbc" + }, + + // + // HTML Tags + // + + { + "name": "HTML: Doctype Declaration", + "scope": "meta.tag.sgml.doctype", + "foreground": "#808080" + }, + { + "name": "HTML: Tags", + "scope": "meta.tag", + "foreground": "#555555" + }, + { + "name": "HTML: Tag Punctuation", + "scope": "meta.tag punctuation.definition.tag - markup.raw", + "foreground": "#6e5330" + }, + { + "name": "HTML: Attribute Names", + "scope": "meta.tag entity.other.attribute-name", + "foreground": "#666666" + }, + { + "name": "HTML: Attribute Values Text", + "scope": "meta.tag string, meta.tag constant.character", + "foreground": "#926730" + }, + { + "name": "HTML: Attribute Values Punctuation", + "scope": "meta.tag string punctuation.definition.string", + "foreground": "#6e5330" + }, + { + "name": "HTML: Entities", + "scope": "constant.character.entity, constant.character.entity punctuation", + "foreground": "#926730" + }, + + // + // Markdown Elements + // + + { + "name": "Markdown: Meta Data", + "scope": "meta.header.multimarkdown, meta.header.multimarkdown & (constant | keyword | string | punctuation.definition | punctuation.separator.key-value)", + "foreground": "#C77E77" + }, + { + "name": "Markdown: Heading", + "scope": "markup.heading", + "foreground": "#C77E77", + "font_style": "bold" + }, + { + "name": "Markdown: Blockquote", + "scope": "markup.quote", + "foreground": "#666666" + }, + { + "name": "Markdown: Blockquote (Tags)", + "scope": "markup.quote entity.name.tag, markup.quote meta.tag, markup.quote meta.tag punctuation.definition.tag, markup.quote meta.tag string, markup.quote meta.tag string punctuation.definition.string, markup.quote meta.tag entity.other.attribute-name", + "foreground": "#505050" + }, + { + "name": "Markdown: Blockquote (Keyboard Shortcut)", + "scope": "markup.quote markup.kbd.content", + "foreground": "#8e8e8e", + "background": "#2e3240" + }, + { + "name": "Markdown: Blockquote (Bold)", + "scope": "markup.quote markup.bold, markup.quote markup.italic, markup.quote markup.bold_italic", + "foreground": "#666666" + }, + { + "name": "Markdown: Blockquote Punctuation", + "scope": "markup.quote punctuation.definition.blockquote", + "foreground": "#3E3E3E", + "background": "#3E3E3E" + }, + { + "name": "Markdown: Block code", + "scope": "markup.raw.block, markup.raw.code-fence", + "foreground": "#aaaaaa", + "background": "#2e3240" + }, + { + "name": "Markdown: Inline code", + "scope": "markup.raw.inline", + "background": "#2e3240" + }, + { + "name": "Markdown: Link Description", + "scope": "meta.link.inline.description, meta.link.reference.description, meta.image.reference.description", + "foreground": "#5294E2" + }, + { + "name": "Markdown: Link URL", + "scope": "markup.underline.link, constant.other.reference.link", + "foreground": "#555555" + }, + { + "name": "Markup: Plain Link", + "scope": "meta.link.inet markup.underline.link, meta.link.email.lt-gt markup.underline.link", + "foreground": "#bbbb77" + }, + { + "name": "Markdown: Punctuation", + "scope": "(punctuation.definition | punctuation.section | punctuation.separator) - markup.raw, punctuation.definition.raw", + "foreground": "#555555" + }, + { + "name": "Markdown: List Text", + "scope": "markup.list", + "foreground": "#ffffff" + }, + { + "name": "Markdown: Ordered List Bullets", + "scope": "markup.list.numbered.bullet, markup.list.numbered.bullet punctuation.definition", + "foreground": "#ffffff" + }, + { + "name": "Markdown: Unordered List Bullets", + "scope": "markup.list.unnumbered.bullet, markup.list.unnumbered.bullet punctuation.definition", + "foreground": "#ffffff" + }, + { + "name": "Markdown: Task Check Box", + "scope": "markup.checkbox, markup.checkbox punctuation.definition", + "foreground": "#ffffff", + "background": "color(white a(5%))" + }, + { + "name": "Markdown: Task Check Mark", + "scope": "markup.checkbox.mark", + "foreground": "#BBBBBB" + }, + { + "name": "Markdown: Keyboard Shortcut", + "scope": "markup.kbd.content", + "foreground": "#ECECEC" + }, + { + "name": "Markdown: Hard Line Breaks", + "scope": "punctuation.definition.hard-line-break", + "background": "#2e3240" + }, + { + "name": "Markdown: Thematic Break", + "scope": "meta.separator.thematic-break, meta.separator.thematic-break punctuation.definition", + "foreground": "#555555", + "background": "#2e3240" + }, + + // + // Inline Formatting + // + + { + "name": "Markup: Emphasis", + "scope": "markup.italic - markup.bold", + "foreground": "#888888", + "font_style": "italic" + }, + { + "name": "Markup: Strong", + "scope": "markup.bold - markup.italic", + "foreground": "#E8A64B", + "font_style": "bold" + }, + { + "name": "Markup: StrongEmphasis", + "scope": "markup.bold_italic, markup.bold & markup.italic", + "foreground": "#E8A64B", + "font_style": "bold italic" + }, + { + "name": "Markup: Strikethrough", + "scope": "markup.strikethrough, markup.strikethrough & (markup.bold | markup.italic | meta.tag entity | meta.tag punctuation.definition.tag)", + "foreground": "#313131" + }, + { + "name": "Markup: Strikethrough (Keyboard Shortcut)", + "scope": "markup.strikethrough markup.kbd.content", + "foreground": "#484848" + }, + + // + // Markups + // + + { + "name": "Markup: Output", + "scope": "markup.output, markup.raw", + "foreground": "#808080" + }, + { + "name": "Markup: Prompt", + "scope": "markup.prompt", + "foreground": "#aaaaaa" + }, + + // + // CriticMarkup + // + + { + "name": "Critics: Addition", + "scope": "markup.critic.addition, markup.critic.addition markup.inserted", + "foreground": "var(critic_inserted_fg)", + "background": "var(critic_inserted_bg)" + }, + { + "name": "Critics: Addition Punctuation", + "scope": "markup.critic.addition punctuation.definition", + "foreground": "var(critic_inserted_punct)" + }, + { + "name": "Critics: Deletion", + "scope": "markup.critic.deletion, markup.critic.deletion markup.deleted", + "foreground": "var(critic_deleted_fg)", + "background": "var(critic_deleted_bg)" + }, + { + "name": "Critics: Deletion Punctuation", + "scope": "markup.critic.deletion punctuation.definition", + "foreground": "var(critic_deleted_punct)" + }, + { + "name": "Critics: Comment", + "scope": "markup.critic.comment", + "foreground": "var(critic_comment_fg)", + "background": "var(critic_comment_bg)" + }, + { + "name": "Critics: Comment Punctuation", + "scope": "markup.critic.comment punctuation.definition", + "foreground": "var(critic_comment_punct)" + }, + { + "name": "Critics: Highlight", + "scope": "markup.critic.highlight, markup.critic.highlight markup.info", + "foreground": "var(critic_highlight_fg)", + "background": "var(critic_highlight_bg)" + }, + { + "name": "Critics: Highlight Punctuation", + "scope": "markup.critic.highlight punctuation.definition", + "foreground": "var(critic_highlight_punct)" + }, + { + "name": "Critics: Substitution Punctuation", + "scope": "markup.critic.substitution punctuation.definition, markup.critic.substitution punctuation.separator", + "foreground": "var(critic_substitution_punct)", + "background": "var(critic_substitution_bg)" + }, + { + "name": "Critics: Substitution Deletion", + "scope": "markup.critic.substitution, markup.critic.substitution markup.deleted", + "foreground": "var(critic_deleted_fg)", + "background": "var(critic_substitution_bg)" + }, + { + "name": "Critics: Substitution Replacement", + "scope": "markup.critic.substitution, markup.critic.substitution markup.inserted ", + "foreground": "var(critic_inserted_fg)", + "background": "var(critic_substitution_bg)" + }, + + // + // Diffs + // + + { + "name": "Diff: Header Range", + "scope": "meta.diff.range, meta.diff.index, meta.separator", + "foreground": "var(diff_header_range_fg)", + "background": "var(diff_header_range_bg)" + }, + { + "name": "Diff: Header From", + "scope": "meta.diff.header.from-file", + "foreground": "var(diff_header_from_fg)", + "background": "var(diff_header_from_bg)" + }, + { + "name": "Diff: Header To", + "scope": "meta.diff.header.to-file", + "foreground": "var(diff_header_to_fg)", + "background": "var(diff_header_to_bg)" + }, + { + "name": "Diff: Deleted", + "scope": "markup.deleted, markup.deleted punctuation.definition", + "foreground": "var(diff_deleted_fg)", + "background": "var(diff_deleted_bg)" + }, + { + "name": "Diff: Inserted", + "scope": "markup.inserted, markup.inserted punctuation.definition", + "foreground": "var(diff_inserted_fg)", + "background": "var(diff_inserted_bg)" + }, + { + "name": "Diff: Changed", + "scope": "markup.changed, markup.changed punctuation.definition", + "foreground": "var(diff_changed_fg)", + "background": "var(diff_changed_bg)" + }, + { + "name": "Diff: Ignored", + "scope": "markup.ignored, markup.ignored punctuation.definition", + "foreground": "var(diff_ignored_fg)", + "background": "var(diff_ignored_bg)" + }, + { + "name": "Diff: Untracked", + "scope": "markup.untracked, markup.untracked punctuation.definition", + "foreground": "var(diff_untracked_fg)", + "background": "var(diff_untracked_bg)" + }, + + // + // Linter + // + + { + "name": "Markup: Info", + "scope": "markup.info", + "foreground": "var(info_fg)", + "background": "var(info_bg)" + }, + { + "name": "Markup: Error", + "scope": "markup.error, markup.traceback, sublimelinter.mark.error", + "foreground": "var(error_fg)", + "background": "var(error_bg)" + }, + { + "name": "Markup: Warning", + "scope": "markup.warning, sublimelinter.mark.warning", + "foreground": "var(warning_fg)", + "background": "var(warning_bg)" + }, + + // + // Plugins + // + + { + "name": "Block Cursor", + "scope": "block_cursor", + "foreground": "#212121", + "background": "#00bdff77" + }, + { + "name": "Brackets", + "scope": "entity.name.class", + "background": "#2e3240" + }, + { + "name": "BracketHighlighter", + "scope": "brackethighlighter.default", + "foreground": "#dedede", + "background": "#FF420077" + }, + { + "name": "WordHighlight", + "scope": "wordhighlight", + "foreground": "#dedede", + "background": "#FF420077" + }, + { + "name": "Highlight: Color Warm Blue", + "scope": "highlight.color.ADD8E6", + "foreground": "#ADD8E6" + }, + { + "name": "Highlight: Color MistyRose", + "scope": "highlight.color.FFE4E1", + "foreground": "#FFE4E1" + }, + { + "name": "Highlight: Color Green Tea", + "scope": "highlight.color.D0F0C0", + "foreground": "#D0F0C0" + } + ] +} diff --git a/schemes/MarkdownEditor-Dark.sublime-color-scheme b/schemes/MarkdownEditor-Dark.sublime-color-scheme new file mode 100644 index 00000000..2e10ae77 --- /dev/null +++ b/schemes/MarkdownEditor-Dark.sublime-color-scheme @@ -0,0 +1,567 @@ +{ + "name": "MarkdownEditing", + "author": "Unknown", + "variables": { + + // Critic Markup + + "critic_inserted_fg": "#46a524", + "critic_inserted_bg": "color(var(critic_inserted_fg) a(7%))", + "critic_inserted_punct": "color(var(critic_inserted_fg) a(40%))", + + "critic_deleted_fg": "#f92672", + "critic_deleted_bg": "color(var(critic_deleted_fg) a(7%))", + "critic_deleted_punct": "color(var(critic_deleted_fg) a(40%))", + + "critic_comment_fg": "#7f7f7f", + "critic_comment_bg": "color(var(critic_comment_fg) a(7%))", + "critic_comment_punct": "color(var(critic_comment_fg) a(40%))", + + "critic_highlight_fg": "#6d98cf", + "critic_highlight_bg": "color(var(critic_highlight_fg) a(7%))", + "critic_highlight_punct": "color(var(critic_highlight_fg) a(40%))", + + "critic_substitution_fg": "#ddb700", + "critic_substitution_bg": "color(var(critic_substitution_fg) a(7%))", + "critic_substitution_punct": "color(var(critic_substitution_fg) a(80%))", + + // Diff Markup + + "diff_header_range_fg": "#bcbcbc", + "diff_header_range_bg": "#150d0a", + "diff_header_from_fg": "var(diff_header_range_fg)", + "diff_header_from_bg": "#002222", + "diff_header_to_fg": "var(diff_header_range_fg)", + "diff_header_to_bg": "#220022", + "diff_deleted_fg": "#F92672", + "diff_deleted_bg": "color(var(diff_deleted_fg) a(7%))", + "diff_inserted_fg": "#A6E22E", + "diff_inserted_bg": "color(var(diff_inserted_fg) a(7%))", + "diff_changed_fg": "#967EFB", + "diff_changed_bg": "color(var(diff_changed_fg) a(7%))", + "diff_ignored_fg": "#565656", + "diff_ignored_bg": "color(var(diff_ignored_fg) a(7%))", + "diff_untracked_fg": "#565656", + "diff_untracked_bg": "color(var(diff_untracked_fg) a(7%))", + + // Linter Markup + + "info_fg": "#61862F", + "info_bg": "transparent", + "error_fg": "#D02000", + "error_bg": "transparent", + "warning_fg": "#DDB700", + "warning_bg": "transparent" + }, + "globals": + { + "foreground": "#aaaaaa", + "background": "#131313", + "caret": "#00bbff", + "invisibles": "#1f1f1f", + "line_highlight": "#191919", + "selection": "#3d1700", + "selection_border": "#553420", + "inactive_selection": "#4a2c1a", + "shadow": "#7f7f7f", + "shadow_width": "6", + "find_highlight_foreground": "#ffffff", + "find_highlight": "#00186d" + }, + "rules": + [ + { + "name": "Comments", + "scope": "comment, comment punctuation", + "foreground": "#525252" + }, + { + "name": "Comments: Preprocessor", + "scope": "comment.block.preprocessor", + "foreground": "#525252" + }, + { + "name": "Invalid - Deprecated", + "scope": "invalid.deprecated", + "background": "#103030", + "font_style": "italic underline" + }, + { + "name": "Invalid - Illegal", + "scope": "invalid.illegal", + "foreground": "#060d31" + }, + { + "name": "Keywords", + "scope": "keyword, storage", + "foreground": "#9e79d0" + }, + { + "name": "Operators", + "scope": "keyword.operator", + "foreground": "#9d9036" + }, + { + "name": "Types", + "scope": "keyword.declaration, storage.type, support.type", + "foreground": "#98ff46" + }, + { + "name": "Functions", + "scope": "entity.name.function, support.function, entity", + "foreground": "#9e79d0" + }, + { + "name": "Classes", + "scope": "entity.name.type, entity.other.inherited-class, support.class", + "foreground": "#c5e28d" + }, + { + "name": "Exceptions", + "scope": "entity.name.exception", + "foreground": "#06cdcd" + }, + { + "name": "Sections", + "scope": "entity.name.section", + "foreground": "#cccccc", + "font_style": "bold" + }, + { + "name": "Numbers", + "scope": "constant, constant.numeric", + "foreground": "#89ac3e", + "background": "#0c0d00" + }, + { + "name": "Punctuation", + "scope": "punctuation", + "foreground": "#ffffff" + }, + { + "name": "Strings", + "scope": "string, constant.character", + "foreground": "#4398f0", + "background": "#0416521A" + }, + { + "name": "Strings: Punctuation", + "scope": "string punctuation", + "foreground": "#1965b3" + }, + { + "name": "Strings: Escape Sequences", + "scope": "constant.character.escape", + "background": "#041652CC", + "font_style": "bold" + }, + { + "name": "Strings: Symbols", + "scope": "constant.other.symbol", + "background": "#17002a", + "font_style": "bold" + }, + { + "name": "Embedded Source", + "scope": "string source, text source", + "foreground": "#bcbcbc" + }, + + // + // HTML Tags + // + + { + "name": "HTML: Doctype Declaration", + "scope": "meta.tag.sgml.doctype", + "foreground": "#808080" + }, + { + "name": "HTML: Tags", + "scope": "meta.tag", + "foreground": "#555555", + "background": "#131313" + }, + { + "name": "HTML: Tag Punctuation", + "scope": "meta.tag punctuation.definition.tag - markup.raw", + "foreground": "#6e5330" + }, + { + "name": "HTML: Attribute Names", + "scope": "meta.tag entity.other.attribute-name", + "foreground": "#666666" + }, + { + "name": "HTML: Attribute Values Text", + "scope": "meta.tag string, meta.tag constant.character", + "foreground": "#926730" + }, + { + "name": "HTML: Attribute Values Punctuation", + "scope": "meta.tag string punctuation.definition.string", + "foreground": "#6e5330" + }, + { + "name": "HTML: Entities", + "scope": "constant.character.entity, constant.character.entity punctuation", + "foreground": "#926730" + }, + + // + // Markdown Elements + // + + { + "name": "Markdown: Meta Data", + "scope": "meta.header.multimarkdown, meta.header.multimarkdown & (constant | keyword | string | punctuation.definition | punctuation.separator.key-value)", + "foreground": "#444444", + "background": "#222222" + }, + { + "name": "Markdown: Heading", + "scope": "markup.heading", + "font_style": "bold" + }, + { + "name": "Markdown: Blockquote", + "scope": "markup.quote", + "foreground": "#666666" + }, + { + "name": "Markdown: Blockquote (Tags)", + "scope": "markup.quote entity.name.tag, markup.quote meta.tag, markup.quote meta.tag punctuation.definition.tag, markup.quote meta.tag string, markup.quote meta.tag string punctuation.definition.string, markup.quote meta.tag entity.other.attribute-name", + "foreground": "#313131", + "background": "#131313" + }, + { + "name": "Markdown: Blockquote (Keyboard Shortcut)", + "scope": "markup.quote markup.kbd.content", + "foreground": "#8e8e8e", + "background": "#1a1a1a" + }, + { + "name": "Markdown: Blockquote (Bold)", + "scope": "markup.quote markup.bold, markup.quote markup.italic, markup.quote markup.bold_italic", + "foreground": "#666666" + }, + { + "name": "Markdown: Blockquote punctuation", + "scope": "markup.quote punctuation.definition.blockquote", + "foreground": "#3E3E3E", + "background": "#3E3E3E" + }, + { + "name": "Markdown: Block code", + "scope": "markup.raw.block, markup.raw.code-fence", + "foreground": "#aaaaaa", + "background": "#212121" + }, + { + "name": "Markdown: Inline code", + "scope": "markup.raw.inline", + "background": "#212121" + }, + { + "name": "Markdown: Link Description", + "scope": "meta.link.inline.description, meta.link.reference.description, meta.image.reference.description", + "foreground": "#cccccc" + }, + { + "name": "Markdown: Link URL", + "scope": "markup.underline.link, constant.other.reference.link", + "foreground": "#555555", + "background": "#171717" + }, + { + "name": "Markdown: Plain Link", + "scope": "meta.link.inet markup.underline.link, meta.link.email.lt-gt markup.underline.link", + "foreground": "#bbbb77" + }, + { + "name": "Markdown: Punctuation", + "scope": "(punctuation.definition | punctuation.section | punctuation.separator) - markup.raw, punctuation.definition.raw", + "foreground": "#555555" + }, + { + "name": "Markdown: List Text", + "scope": "markup.list", + "foreground": "#999999" + }, + { + "name": "Markdown: Ordered List Bullets", + "scope": "markup.list.numbered.bullet, markup.list.numbered.bullet punctuation.definition", + "foreground": "#ffffff" + }, + { + "name": "Markdown: Unordered List Bullets", + "scope": "markup.list.unnumbered.bullet, markup.list.unnumbered.bullet punctuation.definition", + "foreground": "#ffffff" + }, + { + "name": "Markdown: Task Check Box", + "scope": "markup.checkbox, markup.checkbox punctuation.definition", + "foreground": "#ffffff", + "background": "color(white a(5%))" + }, + { + "name": "Markdown: Task Check Mark", + "scope": "markup.checkbox.mark", + "foreground": "#BBBBBB" + }, + { + "name": "Markdown: Keyboard Shortcut", + "scope": "markup.kbd.content", + "foreground": "#ECECEC", + "background": "#2C2C2C" + }, + { + "name": "Markdown: Hard Line Breaks", + "scope": "punctuation.definition.hard-line-break", + "background": "#222222" + }, + { + "name": "Markdown: Thematic Break", + "scope": "meta.separator.thematic-break, meta.separator.thematic-break punctuation.definition", + "foreground": "#555555", + "background": "#44444422" + }, + + // + // Inline Formatting + // + + { + "name": "Markup: Emphasis", + "scope": "markup.italic - markup.bold", + "foreground": "#888888", + "background": "#171717", + "font_style": "italic" + }, + { + "name": "Markup: Strong", + "scope": "markup.bold - markup.italic", + "foreground": "#aaaaaa", + "font_style": "bold" + }, + { + "name": "Markup: StrongEmphasis", + "scope": "markup.bold_italic, markup.bold & markup.italic", + "foreground": "#aaaaaa", + "font_style": "bold italic" + }, + { + "name": "Markup: Strikethrough", + "scope": "markup.strikethrough, markup.strikethrough & (markup.bold | markup.italic | meta.tag entity | meta.tag punctuation.definition.tag)", + "foreground": "#313131", + "background": "#131313" + }, + { + "name": "Markup: Strikethrough (Keyboard Shortcut)", + "scope": "markup.strikethrough markup.kbd.content", + "foreground": "#484848", + "background": "#222222" + }, + + // + // Markups + // + + { + "name": "Markup: Output", + "scope": "markup.output, markup.raw", + "foreground": "#808080" + }, + { + "name": "Markup: Prompt", + "scope": "markup.prompt", + "foreground": "#aaaaaa" + }, + + // + // CriticMarkup + // + + { + "name": "Critics: Addition", + "scope": "markup.critic.addition, markup.critic.addition markup.inserted", + "foreground": "var(critic_inserted_fg)", + "background": "var(critic_inserted_bg)" + }, + { + "name": "Critics: Addition Punctuation", + "scope": "markup.critic.addition punctuation.definition", + "foreground": "var(critic_inserted_punct)" + }, + { + "name": "Critics: Deletion", + "scope": "markup.critic.deletion, markup.critic.deletion markup.deleted", + "foreground": "var(critic_deleted_fg)", + "background": "var(critic_deleted_bg)" + }, + { + "name": "Critics: Deletion Punctuation", + "scope": "markup.critic.deletion punctuation.definition", + "foreground": "var(critic_deleted_punct)" + }, + { + "name": "Critics: Comment", + "scope": "markup.critic.comment", + "foreground": "var(critic_comment_fg)", + "background": "var(critic_comment_bg)" + }, + { + "name": "Critics: Comment Punctuation", + "scope": "markup.critic.comment punctuation.definition", + "foreground": "var(critic_comment_punct)" + }, + { + "name": "Critics: Highlight", + "scope": "markup.critic.highlight, markup.critic.highlight markup.info", + "foreground": "var(critic_highlight_fg)", + "background": "var(critic_highlight_bg)" + }, + { + "name": "Critics: Highlight Punctuation", + "scope": "markup.critic.highlight punctuation.definition", + "foreground": "var(critic_highlight_punct)" + }, + { + "name": "Critics: Substitution Punctuation", + "scope": "markup.critic.substitution punctuation.definition, markup.critic.substitution punctuation.separator", + "foreground": "var(critic_substitution_punct)", + "background": "var(critic_substitution_bg)" + }, + { + "name": "Critics: Substitution Deletion", + "scope": "markup.critic.substitution, markup.critic.substitution markup.deleted", + "foreground": "var(critic_deleted_fg)", + "background": "var(critic_substitution_bg)" + }, + { + "name": "Critics: Substitution Replacement", + "scope": "markup.critic.substitution, markup.critic.substitution markup.inserted ", + "foreground": "var(critic_inserted_fg)", + "background": "var(critic_substitution_bg)" + }, + + // + // Diffs + // + + { + "name": "Diff: Header Range", + "scope": "meta.diff.range, meta.diff.index, meta.separator", + "foreground": "var(diff_header_range_fg)", + "background": "var(diff_header_range_bg)" + }, + { + "name": "Diff: Header From", + "scope": "meta.diff.header.from-file", + "foreground": "var(diff_header_from_fg)", + "background": "var(diff_header_from_bg)" + }, + { + "name": "Diff: Header To", + "scope": "meta.diff.header.to-file", + "foreground": "var(diff_header_to_fg)", + "background": "var(diff_header_to_bg)" + }, + { + "name": "Diff: Deleted", + "scope": "markup.deleted, markup.deleted punctuation.definition", + "foreground": "var(diff_deleted_fg)", + "background": "var(diff_deleted_bg)" + }, + { + "name": "Diff: Inserted", + "scope": "markup.inserted, markup.inserted punctuation.definition", + "foreground": "var(diff_inserted_fg)", + "background": "var(diff_inserted_bg)" + }, + { + "name": "Diff: Changed", + "scope": "markup.changed, markup.changed punctuation.definition", + "foreground": "var(diff_changed_fg)", + "background": "var(diff_changed_bg)" + }, + { + "name": "Diff: Ignored", + "scope": "markup.ignored, markup.ignored punctuation.definition", + "foreground": "var(diff_ignored_fg)", + "background": "var(diff_ignored_bg)" + }, + { + "name": "Diff: Untracked", + "scope": "markup.untracked, markup.untracked punctuation.definition", + "foreground": "var(diff_untracked_fg)", + "background": "var(diff_untracked_bg)" + }, + + // + // Linter + // + + { + "name": "Markup: Info", + "scope": "markup.info", + "foreground": "var(info_fg)", + "background": "var(info_bg)" + }, + { + "name": "Markup: Error", + "scope": "markup.error, markup.traceback, sublimelinter.mark.error", + "foreground": "var(error_fg)", + "background": "var(error_bg)" + }, + { + "name": "Markup: Warning", + "scope": "markup.warning, sublimelinter.mark.warning", + "foreground": "var(warning_fg)", + "background": "var(warning_bg)" + }, + + // + // Plugins + // + + { + "name": "Block Cursor", + "scope": "block_cursor", + "foreground": "#dedede", + "background": "#FF420077" + }, + { + "name": "Brackets", + "scope": "entity.name.class", + "background": "#2A090088" + }, + { + "name": "BracketHighlighter", + "scope": "brackethighlighter.default", + "foreground": "#dedede", + "background": "#FF420077" + }, + { + "name": "WordHighlight", + "scope": "wordhighlight", + "foreground": "#dedede", + "background": "#FF420077" + }, + { + "name": "Highlight: Color Warm Blue", + "scope": "highlight.color.ADD8E6", + "foreground": "#ADD8E6" + }, + { + "name": "Highlight: Color MistyRose", + "scope": "highlight.color.FFE4E1", + "foreground": "#FFE4E1" + }, + { + "name": "Highlight: Color Green Tea", + "scope": "highlight.color.D0F0C0", + "foreground": "#D0F0C0" + } + ] +} diff --git a/schemes/MarkdownEditor-Focus.sublime-color-scheme b/schemes/MarkdownEditor-Focus.sublime-color-scheme new file mode 100644 index 00000000..1ccf2d83 --- /dev/null +++ b/schemes/MarkdownEditor-Focus.sublime-color-scheme @@ -0,0 +1,586 @@ +{ + "name": "MarkdownEditing", + "author": "Unknown", + "variables": { + + // Critic Markup + + "critic_inserted_fg": "#46a524", + "critic_inserted_bg": "color(var(critic_inserted_fg) a(12%))", + "critic_inserted_punct": "color(var(critic_inserted_fg) a(50%))", + + "critic_deleted_fg": "#f92672", + "critic_deleted_bg": "color(var(critic_deleted_fg) a(12%))", + "critic_deleted_punct": "color(var(critic_deleted_fg) a(50%))", + + "critic_comment_fg": "#7f7f7f", + "critic_comment_bg": "color(var(critic_comment_fg) a(7%))", + "critic_comment_punct": "color(var(critic_comment_fg) a(50%))", + + "critic_highlight_fg": "#6d98cf", + "critic_highlight_bg": "color(var(critic_highlight_fg) a(12%))", + "critic_highlight_punct": "color(var(critic_highlight_fg) a(50%))", + + "critic_substitution_fg": "#ddb700", + "critic_substitution_bg": "color(var(critic_substitution_fg) a(12%))", + "critic_substitution_punct": "color(var(critic_substitution_fg) a(100%))", + + // Diff Markup + + "diff_header_range_fg": "#434343", + "diff_header_range_bg": "#EAF2F5", + "diff_header_from_fg": "var(diff_header_range_fg)", + "diff_header_from_bg": "#FFDDDD", + "diff_header_to_fg": "var(diff_header_range_fg)", + "diff_header_to_bg": "#DDFFDD", + "diff_deleted_fg": "#000000", + "diff_deleted_bg": "#FFDDDD", + "diff_inserted_fg": "#000000", + "diff_inserted_bg": "#DDFFDD", + "diff_changed_fg": "#000000", + "diff_changed_bg": "#FFFFDD", + "diff_ignored_fg": "#565656", + "diff_ignored_bg": "color(var(diff_ignored_fg) a(7%))", + "diff_untracked_fg": "#565656", + "diff_untracked_bg": "color(var(diff_untracked_fg) a(7%))", + + // Linter Markup + + "info_fg": "#61862F", + "info_bg": "transparent", + "error_fg": "#F93232", + "error_bg": "transparent", + "warning_fg": "#DDB700", + "warning_bg": "transparent" + }, + "globals": + { + "foreground": "#666666", + "background": "#cccccc", + "caret": "#00bdff", + "invisibles": "#E0E0E0", + "line_highlight": "#f3f3f3", + "selection": "#C2E8FF", + "selection_border": "#AACBDF", + "inactive_selection": "#B5D3E5", + "find_highlight_foreground": "#000000", + "find_highlight": "#FFE792" + }, + "rules": + [ + { + "name": "Comments", + "scope": "comment, comment punctuation", + "foreground": "#ADADAD" + }, + { + "name": "Comments: Preprocessor", + "scope": "comment.block.preprocessor", + "foreground": "#ADADAD" + }, + { + "name": "Comments: Documentation", + "scope": "comment.documentation, comment.block.documentation", + "foreground": "#BC670F", + "background": "#FFFDF7" + }, + { + "name": "Invalid - Deprecated", + "scope": "invalid.deprecated", + "background": "#EFCFCF", + "font_style": "italic underline" + }, + { + "name": "Invalid - Illegal", + "scope": "invalid.illegal", + "foreground": "#F9F2CE" + }, + { + "name": "Keywords", + "scope": "keyword, storage", + "foreground": "#61862F" + }, + { + "name": "Operators", + "scope": "keyword.operator", + "foreground": "#626FC9" + }, + { + "name": "Types", + "scope": "keyword.declaration, storage.type, support.type", + "foreground": "#6700B9" + }, + { + "name": "Language Constants", + "scope": "constant.language, support.constant, variable.language", + "foreground": "#7653C1", + "background": "#E8E8E8" + }, + { + "name": "Variables", + "scope": "variable, support.variable", + "foreground": "#4C8FC7" + }, + { + "name": "Variables: Punctuation", + "scope": "variable punctuation", + "foreground": "#4C8FC7" + }, + { + "name": "Functions", + "scope": "entity.name.function, support.function, entity", + "foreground": "#61862F" + }, + { + "name": "Classes", + "scope": "entity.name.type, entity.other.inherited-class, support.class", + "foreground": "#3A1D72" + }, + { + "name": "Exceptions", + "scope": "entity.name.exception", + "foreground": "#F93232" + }, + { + "name": "Sections", + "scope": "entity.name.section", + "foreground": "#666666", + "font_style": "bold" + }, + { + "name": "Numbers", + "scope": "constant, constant.numeric", + "foreground": "#7653C1" + }, + { + "name": "Punctuation", + "scope": "punctuation", + "foreground": "#000000" + }, + { + "name": "Strings", + "scope": "string, constant.character", + "foreground": "#BC670F" + }, + { + "name": "Strings: Punctuation", + "scope": "string punctuation", + "foreground": "#E69A4C" + }, + { + "name": "Strings: Escape Sequences", + "scope": "constant.character.escape", + "background": "#FBE9ADCC", + "font_style": "bold" + }, + { + "name": "Strings: Regular Expressions", + "scope": "string.regexp", + "foreground": "#699D36" + }, + { + "name": "Strings: Symbols", + "scope": "constant.other.symbol", + "background": "#E8FFD5", + "font_style": "bold" + }, + { + "name": "Embedded Source", + "scope": "string source, text source", + "foreground": "#434343" + }, + + // + // HTML Tags + // + + { + "name": "HTML: Doctype Declaration", + "scope": "meta.tag.sgml.doctype", + "foreground": "#7F7F7F" + }, + { + "name": "HTML: Tags", + "scope": "meta.tag", + "foreground": "#AAAAAA" + }, + { + "name": "HTML: Tags", + "scope": "meta.disable-markdown", + "foreground": "#999999" + }, + { + "name": "HTML: Tag Punctuation", + "scope": "meta.tag punctuation.definition.tag - markup.raw", + "foreground": "#4F9FCF" + }, + { + "name": "HTML: Attribute Names", + "scope": "meta.tag entity.other.attribute-name", + "foreground": "#4F9FCF" + }, + { + "name": "HTML: Attribute Values Text", + "scope": "meta.tag string, meta.tag constant.character", + "foreground": "#D44950" + }, + { + "name": "HTML: Attribute Values Punctuation", + "scope": "meta.tag string punctuation.definition.string", + "foreground": "#5FAFEF" + }, + { + "name": "HTML: Entities", + "scope": "constant.character.entity, constant.character.entity punctuation", + "foreground": "#000000" + }, + { + "name": "CSS: Selectors", + "scope": "meta.selector, meta.selector entity, meta.selector entity punctuation, entity.name.tag.css", + "foreground": "#3A77BF" + }, + { + "name": "CSS: Property Names", + "scope": "meta.property-name, support.type.property-name", + "foreground": "#D4430D" + }, + { + "name": "CSS: Property Values", + "scope": "meta.property-value constant.numeric, meta.property-value constant, meta.property-value keyword", + "foreground": "#43A202", + "background": "#FFFFFF" + }, + + // + // Markdown Elements + // + + { + "name": "Markdown: Meta Data", + "scope": "meta.header.multimarkdown, meta.header.multimarkdown & (constant | keyword | string | punctuation.definition | punctuation.separator.key-value)", + "foreground": "#BBBBBB", + "background": "#DDDDDD" + }, + { + "name": "Markdown: Heading", + "scope": "markup.heading", + "foreground": "#777777", + "font_style": "bold" + }, + { + "name": "Markdown: Blockquote punctuation", + "scope": "markup.quote punctuation.definition.blockquote", + "foreground": "#D0D0D0", + "background": "#D0D0D0" + }, + { + "name": "Block Code", + "scope": "markup.raw.block, markup.raw.code-fence", + "foreground": "#555555", + "background": "#dedede" + }, + { + "name": "Inline Code", + "scope": "markup.raw.inline", + "background": "#dedede" + }, + { + "name": "Markdown: Link Description", + "scope": "meta.link.inline.description, meta.link.reference.description, meta.image.reference.description", + "foreground": "#333333" + }, + { + "name": "Markdown: Link URL", + "scope": "markup.underline.link, constant.other.reference.link", + "foreground": "#AAAAAA" + }, + { + "name": "Markdown: Plain Link", + "scope": "meta.link.inet markup.underline.link, meta.link.email.lt-gt markup.underline.link", + "foreground": "#444488" + }, + { + "name": "Markdown: Punctuation", + "scope": "(punctuation.definition | punctuation.section | punctuation.separator) - markup.raw, punctuation.definition.raw", + "foreground": "#AAAAAA" + }, + { + "name": "Markdown: List Text", + "scope": "markup.list", + "foreground": "#666666" + }, + { + "name": "Markdown: Ordered List Bullets", + "scope": "markup.list.numbered.bullet, markup.list.numbered.bullet punctuation.definition", + "foreground": "#666666" + }, + { + "name": "Markdown: Unordered List Bullets", + "scope": "markup.list.unnumbered.bullet, markup.list.unnumbered.bullet punctuation.definition", + "foreground": "#666666" + }, + { + "name": "Markdown: Task Check Box", + "scope": "markup.checkbox, markup.checkbox punctuation.definition", + "foreground": "#666666", + "background": "color(black a(3%))" + }, + { + "name": "Markdown: Task Check Mark", + "scope": "markup.checkbox.mark", + "foreground": "#666666" + }, + { + "name": "Markdown: Keyboard Shortcut", + "scope": "markup.kbd.content", + "foreground": "#131313", + "background": "#D3D3D3" + }, + { + "name": "Markdown: Hard Line Breaks", + "scope": "punctuation.definition.hard-line-break", + "background": "#d5d5d5" + }, + { + "name": "Markdown: Thematic Break", + "scope": "meta.separator.thematic-break, meta.separator.thematic-break punctuation.definition", + "foreground": "#AAAAAA", + "background": "#BBBBBB" + }, + + // + // Inline Formatting + // + + { + "name": "Markup: Emphasis", + "scope": "markup.italic - markup.bold", + "foreground": "#777777", + "font_style": "italic" + }, + { + "name": "Markup: Strong", + "scope": "markup.bold - markup.italic", + "foreground": "#777777", + "font_style": "bold" + }, + { + "name": "Markup: StrongEmphasis", + "scope": "markup.bold_italic, markup.bold & markup.italic", + "foreground": "#777777", + "font_style": "bold italic" + }, + { + "name": "Markup: Strikethrough", + "scope": "markup.strikethrough, markup.strikethrough & (markup.bold | markup.italic | meta.tag entity | meta.tag punctuation.definition.tag)", + "foreground": "#aaaaaa" + }, + { + "name": "Markup: Strikethrough (Keyboard Shortcut)", + "scope": "markup.strikethrough markup.kbd.content", + "foreground": "#aaaaaa", + "background": "#cccccc" + }, + + // + // Markups + // + + { + "name": "Markup: Output", + "scope": "markup.output, markup.raw", + "foreground": "#7F7F7F" + }, + { + "name": "Markup: Prompt", + "scope": "markup.prompt", + "foreground": "#555555" + }, + + // + // CriticMarkup + // + + { + "name": "Critics: Addition", + "scope": "markup.critic.addition, markup.critic.addition markup.inserted", + "foreground": "var(critic_inserted_fg)", + "background": "var(critic_inserted_bg)" + }, + { + "name": "Critics: Addition Punctuation", + "scope": "markup.critic.addition punctuation.definition", + "foreground": "var(critic_inserted_punct)" + }, + { + "name": "Critics: Deletion", + "scope": "markup.critic.deletion, markup.critic.deletion markup.deleted", + "foreground": "var(critic_deleted_fg)", + "background": "var(critic_deleted_bg)" + }, + { + "name": "Critics: Deletion Punctuation", + "scope": "markup.critic.deletion punctuation.definition", + "foreground": "var(critic_deleted_punct)" + }, + { + "name": "Critics: Comment", + "scope": "markup.critic.comment", + "foreground": "var(critic_comment_fg)", + "background": "var(critic_comment_bg)" + }, + { + "name": "Critics: Comment Punctuation", + "scope": "markup.critic.comment punctuation.definition", + "foreground": "var(critic_comment_punct)" + }, + { + "name": "Critics: Highlight", + "scope": "markup.critic.highlight, markup.critic.highlight markup.info", + "foreground": "var(critic_highlight_fg)", + "background": "var(critic_highlight_bg)" + }, + { + "name": "Critics: Highlight Punctuation", + "scope": "markup.critic.highlight punctuation.definition", + "foreground": "var(critic_highlight_punct)" + }, + { + "name": "Critics: Substitution Punctuation", + "scope": "markup.critic.substitution punctuation.definition, markup.critic.substitution punctuation.separator", + "foreground": "var(critic_substitution_punct)", + "background": "var(critic_substitution_bg)" + }, + { + "name": "Critics: Substitution Deletion", + "scope": "markup.critic.substitution, markup.critic.substitution markup.deleted", + "foreground": "var(critic_deleted_fg)", + "background": "var(critic_substitution_bg)" + }, + { + "name": "Critics: Substitution Replacement", + "scope": "markup.critic.substitution, markup.critic.substitution markup.inserted ", + "foreground": "var(critic_inserted_fg)", + "background": "var(critic_substitution_bg)" + }, + + // + // Diffs + // + + { + "name": "Diff: Header Range", + "scope": "meta.diff.range, meta.diff.index, meta.separator", + "foreground": "var(diff_header_range_fg)", + "background": "var(diff_header_range_bg)" + }, + { + "name": "Diff: Header From", + "scope": "meta.diff.header.from-file", + "foreground": "var(diff_header_from_fg)", + "background": "var(diff_header_from_bg)" + }, + { + "name": "Diff: Header To", + "scope": "meta.diff.header.to-file", + "foreground": "var(diff_header_to_fg)", + "background": "var(diff_header_to_bg)" + }, + { + "name": "Diff: Deleted", + "scope": "markup.deleted, markup.deleted punctuation.definition", + "foreground": "var(diff_deleted_fg)", + "background": "var(diff_deleted_bg)" + }, + { + "name": "Diff: Inserted", + "scope": "markup.inserted, markup.inserted punctuation.definition", + "foreground": "var(diff_inserted_fg)", + "background": "var(diff_inserted_bg)" + }, + { + "name": "Diff: Changed", + "scope": "markup.changed, markup.changed punctuation.definition", + "foreground": "var(diff_changed_fg)", + "background": "var(diff_changed_bg)" + }, + { + "name": "Diff: Ignored", + "scope": "markup.ignored, markup.ignored punctuation.definition", + "foreground": "var(diff_ignored_fg)", + "background": "var(diff_ignored_bg)" + }, + { + "name": "Diff: Untracked", + "scope": "markup.untracked, markup.untracked punctuation.definition", + "foreground": "var(diff_untracked_fg)", + "background": "var(diff_untracked_bg)" + }, + + // + // Linter + // + + { + "name": "Markup: Info", + "scope": "markup.info", + "foreground": "var(info_fg)", + "background": "var(info_bg)" + }, + { + "name": "Markup: Error", + "scope": "markup.error, markup.traceback, sublimelinter.mark.error", + "foreground": "var(error_fg)", + "background": "var(error_bg)" + }, + { + "name": "Markup: Warning", + "scope": "markup.warning, sublimelinter.mark.warning", + "foreground": "var(warning_fg)", + "background": "var(warning_bg)" + }, + + // + // Plugins + // + + { + "name": "Block Cursor", + "scope": "block_cursor", + "foreground": "#212121", + "background": "#00bdff77" + }, + { + "name": "Brackets", + "scope": "entity.name.class", + "background": "#d5f6ff88" + }, + { + "name": "BracketHighlighter", + "scope": "brackethighlighter.default", + "foreground": "#212121", + "background": "#00bdff77" + }, + { + "name": "WordHighlight", + "scope": "wordhighlight", + "foreground": "#212121", + "background": "#00bdff77" + }, + { + "name": "Highlight: Color Warm Blue", + "scope": "highlight.color.ADD8E6", + "foreground": "#ADD8E6" + }, + { + "name": "Highlight: Color MistyRose", + "scope": "highlight.color.FFE4E1", + "foreground": "#FFE4E1" + }, + { + "name": "Highlight: Color Green Tea", + "scope": "highlight.color.D0F0C0", + "foreground": "#D0F0C0" + } + ] +} diff --git a/schemes/MarkdownEditor-Yellow.sublime-color-scheme b/schemes/MarkdownEditor-Yellow.sublime-color-scheme new file mode 100644 index 00000000..8748ddbe --- /dev/null +++ b/schemes/MarkdownEditor-Yellow.sublime-color-scheme @@ -0,0 +1,565 @@ +{ + "name": "MarkdownEditing", + "author": "Unknown", + "variables": { + + // Critic Markup + + "critic_inserted_fg": "#46a524", + "critic_inserted_bg": "color(var(critic_inserted_fg) a(7%))", + "critic_inserted_punct": "color(var(critic_inserted_fg) a(40%))", + + "critic_deleted_fg": "#f92672", + "critic_deleted_bg": "color(var(critic_deleted_fg) a(7%))", + "critic_deleted_punct": "color(var(critic_deleted_fg) a(40%))", + + "critic_comment_fg": "#7f7f7f", + "critic_comment_bg": "color(var(critic_comment_fg) a(7%))", + "critic_comment_punct": "color(var(critic_comment_fg) a(40%))", + + "critic_highlight_fg": "#6d98cf", + "critic_highlight_bg": "color(var(critic_highlight_fg) a(7%))", + "critic_highlight_punct": "color(var(critic_highlight_fg) a(40%))", + + "critic_substitution_fg": "#ddb700", + "critic_substitution_bg": "color(var(critic_substitution_fg) a(7%))", + "critic_substitution_punct": "color(var(critic_substitution_fg) a(80%))", + + // Diff Markup + + "diff_header_range_fg": "#614234", + "diff_header_range_bg": "#edefbe", + "diff_header_from_fg": "var(diff_header_range_fg)", + "diff_header_from_bg": "#ffdaab", + "diff_header_to_fg": "var(diff_header_range_fg)", + "diff_header_to_bg": "#e2fcab", + "diff_deleted_fg": "#F92672", + "diff_deleted_bg": "color(var(diff_deleted_fg) a(7%))", + "diff_inserted_fg": "#46A524", + "diff_inserted_bg": "color(var(diff_inserted_fg) a(7%))", + "diff_changed_fg": "#700DDB", + "diff_changed_bg": "color(var(diff_changed_fg) a(7%))", + "diff_ignored_fg": "#565656", + "diff_ignored_bg": "color(var(diff_ignored_fg) a(7%))", + "diff_untracked_fg": "#565656", + "diff_untracked_bg": "color(var(diff_untracked_fg) a(7%))", + + // Linter Markup + + "info_fg": "#61862F", + "info_bg": "transparent", + "error_fg": "#D02000", + "error_bg": "transparent", + "warning_fg": "#DDB700", + "warning_bg": "transparent" + }, + "globals": + { + "foreground": "#705442", + "background": "#efe9b7", + "caret": "#28bbc6", + "invisibles": "#e5ddae", + "line_highlight": "#eae3b2", + "selection": "#cce5c6", + "selection_border": "#b7c8ad", + "inactive_selection": "#c1d0b2", + "shadow": "#947e63", + "shadow_width": "6", + "find_highlight_foreground": "#280000", + "find_highlight": "#ffe471" + }, + "rules": + [ + { + "name": "Comments", + "scope": "comment, comment punctuation", + "foreground": "#baab86" + }, + { + "name": "Comments: Preprocessor", + "scope": "comment.block.preprocessor", + "foreground": "#baab86" + }, + { + "name": "Invalid - Deprecated", + "scope": "invalid.deprecated", + "background": "#f2cca1", + "font_style": "italic underline" + }, + { + "name": "Invalid - Illegal", + "scope": "invalid.illegal", + "foreground": "#faefa0" + }, + { + "name": "Keywords", + "scope": "keyword, storage", + "foreground": "#7a8424" + }, + { + "name": "Operators", + "scope": "keyword.operator", + "foreground": "#7b6e9c" + }, + { + "name": "Types", + "scope": "keyword.declaration, storage.type, support.type", + "foreground": "#7f008f" + }, + { + "name": "Functions", + "scope": "entity.name.function, support.function, entity", + "foreground": "#7a8424" + }, + { + "name": "Classes", + "scope": "entity.name.type, entity.other.inherited-class, support.class", + "foreground": "#591d58" + }, + { + "name": "Exceptions", + "scope": "entity.name.exception", + "foreground": "#fa3127" + }, + { + "name": "Sections", + "scope": "entity.name.section", + "foreground": "#533228", + "font_style": "bold" + }, + { + "name": "Numbers", + "scope": "constant, constant.numeric", + "foreground": "#8c5296" + }, + { + "name": "Punctuation", + "scope": "punctuation", + "foreground": "#280000" + }, + { + "name": "Strings", + "scope": "string, constant.character", + "foreground": "#c7660c", + "background": "#fce6861A" + }, + { + "name": "Strings: Punctuation", + "scope": "string punctuation", + "foreground": "#ea983b" + }, + { + "name": "Strings: Escape Sequences", + "scope": "constant.character.escape", + "background": "#fce686CC", + "font_style": "bold" + }, + { + "name": "Strings: Symbols", + "scope": "constant.other.symbol", + "background": "#ecfca5", + "font_style": "bold" + }, + { + "name": "Embedded Source", + "scope": "string source, text source", + "foreground": "#614234" + }, + + // + // HTML Tags + // + + { + "name": "HTML: Doctype Declaration", + "scope": "meta.tag.sgml.doctype", + "foreground": "#937d62" + }, + { + "name": "HTML: Tags", + "scope": "meta.tag", + "foreground": "#b7a884", + "background": "#efe9b7" + }, + { + "name": "HTML: Tag Punctuation", + "scope": "meta.tag punctuation.definition.tag - markup.raw", + "foreground": "#a2aaa1" + }, + { + "name": "HTML: Attribute Names", + "scope": "meta.tag entity.other.attribute-name", + "foreground": "#a99777" + }, + { + "name": "HTML: Attribute Values Text", + "scope": "meta.tag string, meta.tag constant.character", + "foreground": "#8496a1" + }, + { + "name": "HTML: Attribute Values Punctuation", + "scope": "meta.tag string punctuation.definition.string", + "foreground": "#a2aaa1" + }, + { + "name": "HTML: Entities", + "scope": "constant.character.entity, constant.character.entity punctuation", + "foreground": "#8496a1" + }, + + // + // Markdown Elements + // + + { + "name": "Markdown: Meta Data", + "scope": "meta.header.multimarkdown, meta.header.multimarkdown & (constant | keyword | string | punctuation.definition | punctuation.separator.key-value)", + "foreground": "#c6b991", + "background": "#e2daab" + }, + { + "name": "Markdown: Heading", + "scope": "markup.heading", + "font_style": "bold" + }, + { + "name": "Markdown: Blockquote", + "scope": "markup.quote", + "foreground": "#a99777" + }, + { + "name": "Markdown: Blockquote (Tags)", + "scope": "markup.quote entity.name.tag, markup.quote meta.tag, markup.quote meta.tag punctuation.definition.tag, markup.quote meta.tag string, markup.quote meta.tag string punctuation.definition.string, markup.quote meta.tag entity.other.attribute-name", + "foreground": "#d6cba0", + "background": "#efe9b7" + }, + { + "name": "Markdown: Blockquote (Keyboard Shortcut)", + "scope": "markup.quote markup.kbd.content", + "foreground": "#c2b58e", + "background": "#e2daab" + }, + { + "name": "Markdown: Blockquote (Bold)", + "scope": "markup.quote markup.bold, markup.quote markup.italic, markup.quote markup.bold_italic", + "foreground": "#a99777" + }, + { + "name": "Markdown: Blockquote Punctuation", + "scope": "markup.quote punctuation.definition.blockquote", + "foreground": "#d7cda1", + "background": "#d7cda1" + }, + { + "name": "Markdown: Block Code", + "scope": "markup.raw.block, markup.raw.code-fence", + "foreground": "#705442", + "background": "#e3dbac" + }, + { + "name": "Markdown: Inline Code", + "scope": "markup.raw.inline", + "background": "#e3dbac" + }, + { + "name": "Markdown: Link Description", + "scope": "meta.link.inline.description, meta.link.reference.description, meta.image.reference.description", + "foreground": "#533228" + }, + { + "name": "Markdown: Link URL", + "scope": "markup.underline.link, constant.other.reference.link", + "foreground": "#b7a884" + }, + { + "name": "Markdown: Plain Link", + "scope": "meta.link.inet markup.underline.link, meta.link.email.lt-gt markup.underline.link", + "foreground": "#624369" + }, + { + "name": "Markdown: Punctuation", + "scope": "(punctuation.definition | punctuation.section | punctuation.separator) - markup.raw, punctuation.definition.raw", + "foreground": "#b7a884" + }, + { + "name": "Markdown: List Text", + "scope": "markup.list", + "foreground": "#7e654f" + }, + { + "name": "Markdown: Ordered List Bullets", + "scope": "markup.list.numbered.bullet, markup.list.numbered.bullet punctuation.definition", + "foreground": "#280000" + }, + { + "name": "Markdown: Unordered List Bullets", + "scope": "markup.list.unnumbered.bullet, markup.list.unnumbered.bullet punctuation.definition", + "foreground": "#280000" + }, + { + "name": "Markdown: Task Check Box", + "scope": "markup.checkbox, markup.checkbox punctuation.definition", + "foreground": "#280000", + "background": "color(black a(3%))" + }, + { + "name": "Markdown: Task Check Mark", + "scope": "markup.checkbox.mark", + "foreground": "#7e654f" + }, + { + "name": "Markdown: Keyboard Shortcut", + "scope": "markup.kbd.content", + "foreground": "#38130f", + "background": "#dad0a4" + }, + { + "name": "Markdown: Hard Line Breaks", + "scope": "punctuation.definition.hard-line-break", + "background": "#e2daab" + }, + { + "name": "Markdown: Thematic Break", + "scope": "meta.separator.thematic-break, meta.separator.thematic-break punctuation.definition", + "foreground": "#b7a884", + "background": "#c6b99122" + }, + + // + // Inline Formatting + // + + { + "name": "Markup: Emphasis", + "scope": "markup.italic - markup.bold", + "foreground": "#8c755c", + "background": "#ece5b4", + "font_style": "italic" + }, + { + "name": "Markup: Strong", + "scope": "markup.bold - markup.italic", + "foreground": "#705442", + "font_style": "bold" + }, + { + "name": "Markup: StrongEmphasis", + "scope": "markup.bold_italic, markup.bold & markup.italic", + "foreground": "#705442", + "font_style": "bold italic" + }, + { + "name": "Markup: Strikethrough", + "scope": "markup.strikethrough, markup.strikethrough & (markup.bold | markup.italic | meta.tag entity | meta.tag punctuation.definition.tag)", + "foreground": "#d6cba0", + "background": "#efe9b7" + }, + { + "name": "Markup: Strikethrough (Keyboard Shortcut)", + "scope": "markup.strikethrough markup.kbd.content", + "foreground": "#c2b58e", + "background": "#e2daab" + }, + + // + // Markups + // + + { + "name": "Markup: Output", + "scope": "markup.output, markup.raw", + "foreground": "#937d62" + }, + { + "name": "Markup: Prompt", + "scope": "markup.prompt", + "foreground": "#705442" + }, + + // + // CriticMarkup + // + + { + "name": "Critics: Addition", + "scope": "markup.critic.addition, markup.critic.addition markup.inserted", + "foreground": "var(critic_inserted_fg)", + "background": "var(critic_inserted_bg)" + }, + { + "name": "Critics: Addition Punctuation", + "scope": "markup.critic.addition punctuation.definition", + "foreground": "var(critic_inserted_punct)" + }, + { + "name": "Critics: Deletion", + "scope": "markup.critic.deletion, markup.critic.deletion markup.deleted", + "foreground": "var(critic_deleted_fg)", + "background": "var(critic_deleted_bg)" + }, + { + "name": "Critics: Deletion Punctuation", + "scope": "markup.critic.deletion punctuation.definition", + "foreground": "var(critic_deleted_punct)" + }, + { + "name": "Critics: Comment", + "scope": "markup.critic.comment", + "foreground": "var(critic_comment_fg)", + "background": "var(critic_comment_bg)" + }, + { + "name": "Critics: Comment Punctuation", + "scope": "markup.critic.comment punctuation.definition", + "foreground": "var(critic_comment_punct)" + }, + { + "name": "Critics: Highlight", + "scope": "markup.critic.highlight, markup.critic.highlight markup.info", + "foreground": "var(critic_highlight_fg)", + "background": "var(critic_highlight_bg)" + }, + { + "name": "Critics: Highlight Punctuation", + "scope": "markup.critic.highlight punctuation.definition", + "foreground": "var(critic_highlight_punct)" + }, + { + "name": "Critics: Substitution Punctuation", + "scope": "markup.critic.substitution punctuation.definition, markup.critic.substitution punctuation.separator", + "foreground": "var(critic_substitution_punct)", + "background": "var(critic_substitution_bg)" + }, + { + "name": "Critics: Substitution Deletion", + "scope": "markup.critic.substitution, markup.critic.substitution markup.deleted", + "foreground": "var(critic_deleted_fg)", + "background": "var(critic_substitution_bg)" + }, + { + "name": "Critics: Substitution Replacement", + "scope": "markup.critic.substitution, markup.critic.substitution markup.inserted ", + "foreground": "var(critic_inserted_fg)", + "background": "var(critic_substitution_bg)" + }, + + // + // Diffs + // + + { + "name": "Diff: Header Range", + "scope": "meta.diff.range, meta.diff.index, meta.separator", + "foreground": "var(diff_header_range_fg)", + "background": "var(diff_header_range_bg)" + }, + { + "name": "Diff: Header From", + "scope": "meta.diff.header.from-file", + "foreground": "var(diff_header_from_fg)", + "background": "var(diff_header_from_bg)" + }, + { + "name": "Diff: Header To", + "scope": "meta.diff.header.to-file", + "foreground": "var(diff_header_to_fg)", + "background": "var(diff_header_to_bg)" + }, + { + "name": "Diff: Deleted", + "scope": "markup.deleted, markup.deleted punctuation.definition", + "foreground": "var(diff_deleted_fg)", + "background": "var(diff_deleted_bg)" + }, + { + "name": "Diff: Inserted", + "scope": "markup.inserted, markup.inserted punctuation.definition", + "foreground": "var(diff_inserted_fg)", + "background": "var(diff_inserted_bg)" + }, + { + "name": "Diff: Changed", + "scope": "markup.changed, markup.changed punctuation.definition", + "foreground": "var(diff_changed_fg)", + "background": "var(diff_changed_bg)" + }, + { + "name": "Diff: Ignored", + "scope": "markup.ignored, markup.ignored punctuation.definition", + "foreground": "var(diff_ignored_fg)", + "background": "var(diff_ignored_bg)" + }, + { + "name": "Diff: Untracked", + "scope": "markup.untracked, markup.untracked punctuation.definition", + "foreground": "var(diff_untracked_fg)", + "background": "var(diff_untracked_bg)" + }, + + // + // Linter + // + + { + "name": "Markup: Info", + "scope": "markup.info", + "foreground": "var(info_fg)", + "background": "var(info_bg)" + }, + { + "name": "Markup: Error", + "scope": "markup.error, markup.traceback, sublimelinter.mark.error", + "foreground": "var(error_fg)", + "background": "var(error_bg)" + }, + { + "name": "Markup: Warning", + "scope": "markup.warning, sublimelinter.mark.warning", + "foreground": "var(warning_fg)", + "background": "var(warning_bg)" + }, + + // + // Plugins + // + + { + "name": "Block Cursor", + "scope": "block_cursor", + "foreground": "#44211a", + "background": "#28bbc677" + }, + { + "name": "Brackets", + "scope": "entity.name.class", + "background": "#dcf3c688" + }, + { + "name": "BracketHighlighter", + "scope": "brackethighlighter.default", + "foreground": "#44211a", + "background": "#28bbc677" + }, + { + "name": "WordHighlight", + "scope": "wordhighlight", + "foreground": "#44211a", + "background": "#28bbc677" + }, + { + "name": "Highlight: Color Warm Blue", + "scope": "highlight.color.ADD8E6", + "foreground": "#ADD8E6" + }, + { + "name": "Highlight: Color MistyRose", + "scope": "highlight.color.FFE4E1", + "foreground": "#FFE4E1" + }, + { + "name": "Highlight: Color Green Tea", + "scope": "highlight.color.D0F0C0", + "foreground": "#D0F0C0" + } + ] +} diff --git a/schemes/MarkdownEditor.sublime-color-scheme b/schemes/MarkdownEditor.sublime-color-scheme new file mode 100644 index 00000000..9c001f26 --- /dev/null +++ b/schemes/MarkdownEditor.sublime-color-scheme @@ -0,0 +1,564 @@ +{ + "name": "MarkdownEditing", + "author": "Unknown", + "variables": { + + // Critic Markup + + "critic_inserted_fg": "#46a524", + "critic_inserted_bg": "color(var(critic_inserted_fg) a(7%))", + "critic_inserted_punct": "color(var(critic_inserted_fg) a(40%))", + + "critic_deleted_fg": "#f92672", + "critic_deleted_bg": "color(var(critic_deleted_fg) a(7%))", + "critic_deleted_punct": "color(var(critic_deleted_fg) a(40%))", + + "critic_comment_fg": "#7f7f7f", + "critic_comment_bg": "color(var(critic_comment_fg) a(7%))", + "critic_comment_punct": "color(var(critic_comment_fg) a(40%))", + + "critic_highlight_fg": "#6d98cf", + "critic_highlight_bg": "color(var(critic_highlight_fg) a(7%))", + "critic_highlight_punct": "color(var(critic_highlight_fg) a(40%))", + + "critic_substitution_fg": "#ddb700", + "critic_substitution_bg": "color(var(critic_substitution_fg) a(7%))", + "critic_substitution_punct": "color(var(critic_substitution_fg) a(80%))", + + // Diff Markup + + "diff_header_range_fg": "#434343", + "diff_header_range_bg": "#EAF2F5", + "diff_header_from_fg": "var(diff_header_range_fg)", + "diff_header_from_bg": "#FFDDDD", + "diff_header_to_fg": "var(diff_header_range_fg)", + "diff_header_to_bg": "#DDFFDD", + "diff_deleted_fg": "#F92672", + "diff_deleted_bg": "color(var(diff_deleted_fg) a(7%))", + "diff_inserted_fg": "#46A524", + "diff_inserted_bg": "color(var(diff_inserted_fg) a(7%))", + "diff_changed_fg": "#700DDB", + "diff_changed_bg": "color(var(diff_changed_fg) a(7%))", + "diff_ignored_fg": "#565656", + "diff_ignored_bg": "color(var(diff_ignored_fg) a(7%))", + "diff_untracked_fg": "#565656", + "diff_untracked_bg": "color(var(diff_untracked_fg) a(7%))", + + // Linter Markup + + "info_fg": "#61862F", + "info_bg": "transparent", + "error_fg": "#D02000", + "error_bg": "transparent", + "warning_fg": "#DDB700", + "warning_bg": "transparent" + }, + "globals": + { + "foreground": "#555555", + "background": "#ECECEC", + "caret": "#00bbff", + "invisibles": "#E0E0E0", + "line_highlight": "#D3D3D3", + "selection": "#C2E8FF", + "selection_border": "#AACBDF", + "inactive_selection": "#B5D3E5", + "shadow": "#808080", + "shadow_width": "6", + "find_highlight_foreground": "#000000", + "find_highlight": "#FFE792" + }, + "rules": + [ + { + "name": "Comments", + "scope": "comment, comment punctuation", + "foreground": "#ADADAD" + }, + { + "name": "Comments: Preprocessor", + "scope": "comment.block.preprocessor", + "foreground": "#ADADAD" + }, + { + "name": "Invalid - Deprecated", + "scope": "invalid.deprecated", + "background": "#EFCFCF", + "font_style": "italic underline" + }, + { + "name": "Invalid - Illegal", + "scope": "invalid.illegal", + "foreground": "#F9F2CE" + }, + { + "name": "Keywords", + "scope": "keyword, storage", + "foreground": "#61862F" + }, + { + "name": "Operators", + "scope": "keyword.operator", + "foreground": "#626FC9" + }, + { + "name": "Types", + "scope": "keyword.declaration, storage.type, support.type", + "foreground": "#6700B9" + }, + { + "name": "Functions", + "scope": "entity.name.function, support.function, entity", + "foreground": "#61862F" + }, + { + "name": "Classes", + "scope": "entity.name.type, entity.other.inherited-class, support.class", + "foreground": "#3A1D72" + }, + { + "name": "Exceptions", + "scope": "entity.name.exception", + "foreground": "#F93232" + }, + { + "name": "Sections", + "scope": "entity.name.section", + "foreground": "#333333", + "font_style": "bold" + }, + { + "name": "Numbers", + "scope": "constant, constant.numeric", + "foreground": "#7653C1" + }, + { + "name": "Punctuation", + "scope": "punctuation", + "foreground": "#000000" + }, + { + "name": "Strings", + "scope": "string, constant.character", + "foreground": "#BC670F", + "background": "#FBE9AD1A" + }, + { + "name": "Strings: Punctuation", + "scope": "string punctuation", + "foreground": "#E69A4C" + }, + { + "name": "Strings: Escape Sequences", + "scope": "constant.character.escape", + "background": "#FBE9ADCC", + "font_style": "bold" + }, + { + "name": "Strings: Symbols", + "scope": "constant.other.symbol", + "background": "#E8FFD5", + "font_style": "bold" + }, + { + "name": "Embedded Source", + "scope": "string source, text source", + "foreground": "#434343" + }, + + // + // HTML Tags + // + + { + "name": "HTML: Doctype Declaration", + "scope": "meta.tag.sgml.doctype", + "foreground": "#7F7F7F" + }, + { + "name": "HTML: Tags", + "scope": "meta.tag", + "foreground": "#AAAAAA", + "background": "#ECECEC" + }, + { + "name": "HTML: Tag Punctuation", + "scope": "meta.tag punctuation.definition.tag - markup.raw", + "foreground": "#91accf" + }, + { + "name": "HTML: Attribute Names", + "scope": "meta.tag entity.other.attribute-name", + "foreground": "#999999" + }, + { + "name": "HTML: Attribute Values Text", + "scope": "meta.tag string, meta.tag constant.character", + "foreground": "#6d98cf" + }, + { + "name": "HTML: Attribute Values Punctuation", + "scope": "meta.tag string punctuation.definition.string", + "foreground": "#91accf" + }, + { + "name": "HTML: Entities", + "scope": "constant.character.entity, constant.character.entity punctuation", + "foreground": "#6d98cf" + }, + + // + // Markdown Elements + // + + { + "name": "Markdown: Meta Data", + "scope": "meta.header.multimarkdown, meta.header.multimarkdown & (constant | keyword | string | punctuation.definition | punctuation.separator.key-value)", + "foreground": "#BBBBBB", + "background": "#DDDDDD" + }, + { + "name": "Markdown: Heading", + "scope": "markup.heading", + "font_style": "bold" + }, + { + "name": "Markdown: Blockquote", + "scope": "markup.quote", + "foreground": "#999999" + }, + { + "name": "Markdown: Blockquote (Tags)", + "scope": "markup.quote entity.name.tag, markup.quote meta.tag, markup.quote meta.tag punctuation.definition.tag, markup.quote meta.tag string, markup.quote meta.tag string punctuation.definition.string, markup.quote meta.tag entity.other.attribute-name", + "foreground": "#CECECE", + "background": "#ECECEC" + }, + { + "name": "Markdown: Blockquote (Keyboard Shortcut)", + "scope": "markup.quote markup.kbd.content", + "foreground": "#717171", + "background": "#e5e5e5" + }, + { + "name": "Markdown: Blockquote (Bold)", + "scope": "markup.quote markup.bold, markup.quote markup.italic, markup.quote markup.bold_italic", + "foreground": "#999999" + }, + { + "name": "Markdown: Blockquote Punctuation", + "scope": "markup.quote punctuation.definition.blockquote", + "foreground": "#D0D0D0", + "background": "#D0D0D0" + }, + { + "name": "Markdown: Block code", + "scope": "markup.raw.block, markup.raw.code-fence", + "foreground": "#555555", + "background": "#dedede" + }, + { + "name": "Markdown: Inline code", + "scope": "markup.raw.inline", + "background": "#dedede" + }, + { + "name": "Markdown: Link Description", + "scope": "meta.link.inline.description, meta.link.reference.description, meta.image.reference.description", + "foreground": "#333333" + }, + { + "name": "Markdown: Link URL", + "scope": "markup.underline.link, constant.other.reference.link", + "foreground": "#AAAAAA" + }, + { + "name": "Markdown: Plain Link", + "scope": "meta.link.inet markup.underline.link, meta.link.email.lt-gt markup.underline.link", + "foreground": "#444488" + }, + { + "name": "Markdown: Punctuation", + "scope": "(punctuation.definition | punctuation.section | punctuation.separator) - markup.raw, punctuation.definition.raw", + "foreground": "#AAAAAA" + }, + { + "name": "Markdown: List Text", + "scope": "markup.list", + "foreground": "#666666" + }, + { + "name": "Markdown: Ordered List Bullets", + "scope": "markup.list.numbered.bullet, markup.list.numbered.bullet punctuation.definition", + "foreground": "#333333" + }, + { + "name": "Markdown: Unordered List Bullets", + "scope": "markup.list.unnumbered.bullet, markup.list.unnumbered.bullet punctuation.definition", + "foreground": "#333333" + }, + { + "name": "Markdown: Task Check Box", + "scope": "markup.checkbox, markup.checkbox punctuation.definition", + "foreground": "#333333", + "background": "color(black a(3%))" + }, + { + "name": "Markdown: Task Check Mark", + "scope": "markup.checkbox.mark", + "foreground": "#666666" + }, + { + "name": "Markdown: Keyboard Shortcut", + "scope": "markup.kbd.content", + "foreground": "#131313", + "background": "#D3D3D3" + }, + { + "name": "Markdown: Hard Line Breaks", + "scope": "punctuation.definition.hard-line-break", + "background": "#E1E1E1" + }, + { + "name": "Markdown: Thematic Break", + "scope": "meta.separator.thematic-break, meta.separator.thematic-break punctuation.definition", + "foreground": "#AAAAAA", + "background": "#BBBBBB22" + }, + + // + // Inline Formatting + // + + { + "name": "Markup: Emphasis", + "scope": "markup.italic - markup.bold", + "foreground": "#777777", + "background": "#E8E8E8", + "font_style": "italic" + }, + { + "name": "Markup: Strong", + "scope": "markup.bold - markup.italic", + "foreground": "#555555", + "font_style": "bold" + }, + { + "name": "Markup: StrongEmphasis", + "scope": "markup.bold_italic, markup.bold & markup.italic", + "foreground": "#555555", + "font_style": "bold italic" + }, + { + "name": "Markup: Strikethrough", + "scope": "markup.strikethrough, markup.strikethrough & (markup.bold | markup.italic | meta.tag entity | meta.tag punctuation.definition.tag)", + "foreground": "#CECECE" + }, + { + "name": "Markup: Strikethrough (Keyboard Shortcut)", + "scope": "markup.strikethrough markup.kbd.content", + "foreground": "#B7B7B7", + "background": "#E6E6E6" + }, + + // + // Markups + // + + { + "name": "Markup: Output", + "scope": "markup.output, markup.raw", + "foreground": "#7F7F7F" + }, + { + "name": "Markup: Prompt", + "scope": "markup.prompt", + "foreground": "#555555" + }, + + // + // CriticMarkup + // + + { + "name": "Critics: Addition", + "scope": "markup.critic.addition, markup.critic.addition markup.inserted", + "foreground": "var(critic_inserted_fg)", + "background": "var(critic_inserted_bg)" + }, + { + "name": "Critics: Addition Punctuation", + "scope": "markup.critic.addition punctuation.definition", + "foreground": "var(critic_inserted_punct)" + }, + { + "name": "Critics: Deletion", + "scope": "markup.critic.deletion, markup.critic.deletion markup.deleted", + "foreground": "var(critic_deleted_fg)", + "background": "var(critic_deleted_bg)" + }, + { + "name": "Critics: Deletion Punctuation", + "scope": "markup.critic.deletion punctuation.definition", + "foreground": "var(critic_deleted_punct)" + }, + { + "name": "Critics: Comment", + "scope": "markup.critic.comment", + "foreground": "var(critic_comment_fg)", + "background": "var(critic_comment_bg)" + }, + { + "name": "Critics: Comment Punctuation", + "scope": "markup.critic.comment punctuation.definition", + "foreground": "var(critic_comment_punct)" + }, + { + "name": "Critics: Highlight", + "scope": "markup.critic.highlight, markup.critic.highlight markup.info", + "foreground": "var(critic_highlight_fg)", + "background": "var(critic_highlight_bg)" + }, + { + "name": "Critics: Highlight Punctuation", + "scope": "markup.critic.highlight punctuation.definition", + "foreground": "var(critic_highlight_punct)" + }, + { + "name": "Critics: Substitution Punctuation", + "scope": "markup.critic.substitution punctuation.definition, markup.critic.substitution punctuation.separator", + "foreground": "var(critic_substitution_punct)", + "background": "var(critic_substitution_bg)" + }, + { + "name": "Critics: Substitution Deletion", + "scope": "markup.critic.substitution, markup.critic.substitution markup.deleted", + "foreground": "var(critic_deleted_fg)", + "background": "var(critic_substitution_bg)" + }, + { + "name": "Critics: Substitution Replacement", + "scope": "markup.critic.substitution, markup.critic.substitution markup.inserted ", + "foreground": "var(critic_inserted_fg)", + "background": "var(critic_substitution_bg)" + }, + + // + // Diffs + // + + { + "name": "Diff: Header Range", + "scope": "meta.diff.range, meta.diff.index, meta.separator", + "foreground": "var(diff_header_range_fg)", + "background": "var(diff_header_range_bg)" + }, + { + "name": "Diff: Header From", + "scope": "meta.diff.header.from-file", + "foreground": "var(diff_header_from_fg)", + "background": "var(diff_header_from_bg)" + }, + { + "name": "Diff: Header To", + "scope": "meta.diff.header.to-file", + "foreground": "var(diff_header_to_fg)", + "background": "var(diff_header_to_bg)" + }, + { + "name": "Diff: Deleted", + "scope": "markup.deleted, markup.deleted punctuation.definition", + "foreground": "var(diff_deleted_fg)", + "background": "var(diff_deleted_bg)" + }, + { + "name": "Diff: Inserted", + "scope": "markup.inserted, markup.inserted punctuation.definition", + "foreground": "var(diff_inserted_fg)", + "background": "var(diff_inserted_bg)" + }, + { + "name": "Diff: Changed", + "scope": "markup.changed, markup.changed punctuation.definition", + "foreground": "var(diff_changed_fg)", + "background": "var(diff_changed_bg)" + }, + { + "name": "Diff: Ignored", + "scope": "markup.ignored, markup.ignored punctuation.definition", + "foreground": "var(diff_ignored_fg)", + "background": "var(diff_ignored_bg)" + }, + { + "name": "Diff: Untracked", + "scope": "markup.untracked, markup.untracked punctuation.definition", + "foreground": "var(diff_untracked_fg)", + "background": "var(diff_untracked_bg)" + }, + + // + // Linter + // + + { + "name": "Markup: Info", + "scope": "markup.info", + "foreground": "var(info_fg)", + "background": "var(info_bg)" + }, + { + "name": "Markup: Error", + "scope": "markup.error, markup.traceback, sublimelinter.mark.error", + "foreground": "var(error_fg)", + "background": "var(error_bg)" + }, + { + "name": "Markup: Warning", + "scope": "markup.warning, sublimelinter.mark.warning", + "foreground": "var(warning_fg)", + "background": "var(warning_bg)" + }, + + // + // Plugins + // + + { + "name": "Block Cursor", + "scope": "block_cursor", + "foreground": "#212121", + "background": "#00bdff77" + }, + { + "name": "Brackets", + "scope": "entity.name.class", + "background": "#d5f6ff88" + }, + { + "name": "BracketHighlighter", + "scope": "brackethighlighter.default", + "foreground": "#212121", + "background": "#00bdff77" + }, + { + "name": "WordHighlight", + "scope": "wordhighlight", + "foreground": "#212121", + "background": "#00bdff77" + }, + { + "name": "Highlight: Color Warm Blue", + "scope": "highlight.color.ADD8E6", + "foreground": "#ADD8E6" + }, + { + "name": "Highlight: Color MistyRose", + "scope": "highlight.color.FFE4E1", + "foreground": "#FFE4E1" + }, + { + "name": "Highlight: Color Green Tea", + "scope": "highlight.color.D0F0C0", + "foreground": "#D0F0C0" + } + ] +} diff --git a/schemes/Monokai.sublime-color-scheme b/schemes/Monokai.sublime-color-scheme new file mode 100644 index 00000000..725e1597 --- /dev/null +++ b/schemes/Monokai.sublime-color-scheme @@ -0,0 +1,145 @@ +// This patch for Monokai.sublime-color-scheme adds some Markdown specific color definitions +// while making use of well defined colors for code blocks. +{ + "variables": { + "line_break": "color(var(white) alpha(4%))", + "raw_fg": "hsl(210, 10%, 60%)", + "raw_bg": "color(var(white) alpha(4%))" + }, + "rules": [ + + // Basic Formattings + { + "name": "Bold Content", + "scope": "text.html.markdown markup.bold - punctuation.definition.bold", + "font_style": "bold" + }, + { + "name": "Bold Punctuation", + "scope": "text.html.markdown punctuation.definition.bold", + "font_style": "" + }, + { + "name": "Italic Content", + "scope": "text.html.markdown markup.italic - punctuation.definition.italic", + "font_style": "italic" + }, + { + "name": "Italic Punctuation", + "scope": "text.html.markdown punctuation.definition.italic", + "font_style": "" + }, + { + "name": "Bold Italic Content", + "scope": "text.html.markdown markup.bold markup.italic - punctuation.definition.bold - punctuation.definition.italic, text.html.markdown markup.bold_italic - punctuation.definition.bold", + "font_style": "bold italic" + }, + { + "name": "Underlined Content", + "scope": "text.html.markdown markup.underline", + "font_style": "underline" + }, + { + "name": "Bold Underlined Content", + "scope": "text.html.markdown & markup.bold & markup.underline - punctuation.definition.bold", + "font_style": "bold underline" + }, + { + "name": "Italic Underlined Content", + "scope": "text.html.markdown & markup.italic & markup.underline - punctuation.definition.italic", + "font_style": "italic underline" + }, + { + "name": "Bold Italic Underlined Content", + "scope": "text.html.markdown & markup.bold & markup.italic & markup.underline - punctuation.definition.bold - punctuation.definition.italic", + "font_style": "bold underline" + }, + { + "name": "Striked Content", + "scope": "text.html.markdown markup.strikethrough", + "foreground": "var(grey)", + "font_style": "" + }, + { + "name": "Striked References", + "scope": "text.html.markdown markup.strikethrough & (punctuation.definition.constant | punctuation.definition.image | punctuation.definition.link | punctuation.definition.metadata)", + "foreground": "var(grey)", + "font_style": "" + }, + { + "name": "Striked Strings", + "scope": "text.html.markdown markup.strikethrough string", + "foreground": "var(grey)", + "font_style": "" + }, + { + "name": "Markdown: Hard Line Breaks", + "scope": "text.html.markdown punctuation.definition.hard-line-break", + "background": "var(line_break)" + }, + + // Block Quotes + { + "name": "Block Quotes", + "scope": "text.html.markdown markup.quote punctuation.definition.blockquote, text.html.markdown markup.quote punctuation.definition.quote", + "foreground": "var(grey)", + "background": "var(grey)" + }, + + // Code Blocks + { + "name": "Inline Code Block", + "scope": "text.html.markdown markup.raw.inline", + "foreground": "var(raw_fg)", + "background": "var(raw_bg)" + }, + { + "name": "Inline Code Block Punctuation", + "scope": "text.html.markdown markup.raw.inline punctuation.definition.raw", + "foreground": "var(raw_bg)", + "background": "var(raw_bg)" + }, + { + "name": "Raw Code Block", + "scope": "text.html.markdown markup.raw, text.html.markdown meta.code-fence", + "foreground": "var(raw_fg)", + "background": "var(raw_bg)" + }, + + // Inline References + { + "name": "Inline Link URL", + "scope": "text.html.markdown meta.link.inline markup.underline.link", + "foreground": "var(blue)" + }, + + // Keyboard Shortcuts + { + "name": "Keyboard Shortcut Background", + "scope": "text.html.markdown markup.kbd", + "background": "var(raw_bg)" + }, + { + "name": "Keyboard Shortcut Tags", + "scope": "text.html.markdown markup.kbd entity.name.tag, text.html.markdown markup.kbd punctuation.definition.tag", + "foreground": "var(raw_fg)" + }, + { + "name": "Keyboard Shortcut Content", + "scope": "text.html.markdow markup.kbd.content", + "foreground": "var(blue)" + }, + + // Tables + { + "name": "Table Separators / Lines", + "scope": "text.html.markdown meta.table.header-separator punctuation.section, text.html.markdown punctuation.section.table-header, text.html.markdown punctuation.separator.table-cell", + "foreground": "var(grey)" + }, + { + "name": "Table Cell Content Alignment Operator", + "scope": "text.html.markdown meta.table.header-separator punctuation.definition", + "foreground": "var(red2)" + } + ] +} diff --git a/schemes/Preview.md b/schemes/Preview.md new file mode 100644 index 00000000..4ed762ee --- /dev/null +++ b/schemes/Preview.md @@ -0,0 +1,114 @@ +--- +meta: + author: Jon Doe + topic: Samples +--- +# A sample Markdown document + +This is a sample document so you can preview the color schemes. + +## Text Formatting + +Markdown supports _italics_, __bold__, and ___bold italics___ style using underscores. + +Markdown supports *italics*, **bold**, and ***bold italics*** style using asterisks. + +There are also inline styles like `inline code in monospace font` and ~~strikethrough style~~. + +__There may be ~~strikethroughed text~~ or `code text` inside bold text.__ + +_And There may be ~~strikethroughed text~~ or `code text` inside italic text._ + +> __Here is some quotation__. 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. +> +> +> code block +> + +Inline key or ~~key~~ other bold html tags. + + + + + +
column text
+ +## Links and References + +To reference something from a URL, [Named Links][links], +[Inline links](https://example.com/index.html "Description") and direct link like +are of great help. Sometimes ![A picture][sample image] is worth a thousand words. + +--- + +This [[SamplePage]] is a wiki link. + +## Lists + +There are two types of lists, ordered and unordered. + +1. Item 1 + key +2. Item 2 +3. Item 3 + +1) Item 1 +2) Item 2 +3) Item 3 + +* Item A + - Sub list + + Sub sub list + + Sub sub list 2 + - Sub list 2 +* Item B +* Item C + +## Tables + +Col 1 | Col 2 +-----:|------- +what | else + +## Code Blocks + +Anything indented more than 3 characters is treated as raw code block. + + function fibo(n) { + fibo.mem = fibo.mem || []; // I am some comment + return fibo.mem[n] || fibo.mem[n] = n <= 1 ? 1 : fibo(n - 1) + fibo(n - 2); + +Fenced code blocks support syntax highlighting and are wrapped in triple backticks. + +```javascript +function fibo(n) { + fibo.mem = fibo.mem || []; // I am some comment + return fibo.mem[n] || fibo.mem[n] = n <= 1 ? 1 : fibo(n - 1) + fibo(n - 2); +} +``` + +```diff +diff --git a/schemes/Preview.md b/schemes/Preview.md +index 3d4b1fe..a85a22a 100644 +--- a/schemes/Preview.md ++++ b/schemes/Preview.md +@@ -89,6 +89,12 @@ function fibo(n) { + +-## Deleted ++## Inserted +``` + +## CriticMarkup + +This is {++ inserted ++} and {-- deleted --} or {== highlighted ==}{>> comment <<} text. + +We can also {~~ substitute ~> something ~~}. + +## Reference Definitions + +[^1]: This is a footnote definition + +[links]: https://example.com/index.html +[sample image]: https://example.com/sample.png diff --git a/screenshots/arcdark.png b/screenshots/arcdark.png deleted file mode 100644 index 6a242e3a..00000000 Binary files a/screenshots/arcdark.png and /dev/null differ diff --git a/screenshots/dark.png b/screenshots/dark.png deleted file mode 100644 index c477d195..00000000 Binary files a/screenshots/dark.png and /dev/null differ diff --git a/screenshots/fenced-code-block.png b/screenshots/fenced-code-block.png deleted file mode 100644 index f7ca74af..00000000 Binary files a/screenshots/fenced-code-block.png and /dev/null differ diff --git a/screenshots/keyboard-shortcut.png b/screenshots/keyboard-shortcut.png deleted file mode 100644 index 3bcbb7c1..00000000 Binary files a/screenshots/keyboard-shortcut.png and /dev/null differ diff --git a/screenshots/light.png b/screenshots/light.png deleted file mode 100644 index f1e8ff54..00000000 Binary files a/screenshots/light.png and /dev/null differ diff --git a/screenshots/strikethrough.png b/screenshots/strikethrough.png deleted file mode 100644 index 7f734325..00000000 Binary files a/screenshots/strikethrough.png and /dev/null differ diff --git a/screenshots/underscore-in-words.png b/screenshots/underscore-in-words.png deleted file mode 100644 index 489ea4fc..00000000 Binary files a/screenshots/underscore-in-words.png and /dev/null differ diff --git a/screenshots/yellow.png b/screenshots/yellow.png deleted file mode 100644 index 78a303c5..00000000 Binary files a/screenshots/yellow.png and /dev/null differ diff --git a/snippets/Code Block (mdc).sublime-snippet b/snippets/Code Block (mdc).sublime-snippet new file mode 100644 index 00000000..263d1d86 --- /dev/null +++ b/snippets/Code Block (mdc).sublime-snippet @@ -0,0 +1,8 @@ + + + mdc + text.html.markdown - meta.frontmatter - meta.disable-markdown - meta.code-fence - markup.raw + Markdown Codeblock + diff --git a/snippets/Critic Addition.sublime-snippet b/snippets/Critic Addition.sublime-snippet new file mode 100644 index 00000000..b39db20d --- /dev/null +++ b/snippets/Critic Addition.sublime-snippet @@ -0,0 +1,5 @@ + + + text.html.markdown - meta.frontmatter - meta.disable-markdown - markup.critic - meta.code-fence - markup.raw - markup.kbd + Markdown Critic Addition + \ No newline at end of file diff --git a/snippets/Critic Comment.sublime-snippet b/snippets/Critic Comment.sublime-snippet new file mode 100644 index 00000000..1bf92bc4 --- /dev/null +++ b/snippets/Critic Comment.sublime-snippet @@ -0,0 +1,5 @@ + + > ${1:$SELECTION} <<}]]> + text.html.markdown - meta.frontmatter - meta.disable-markdown - markup.critic - meta.code-fence - markup.raw - markup.kbd + Markdown Critic Comment + diff --git a/snippets/Critic Deletion.sublime-snippet b/snippets/Critic Deletion.sublime-snippet new file mode 100644 index 00000000..8d708c9f --- /dev/null +++ b/snippets/Critic Deletion.sublime-snippet @@ -0,0 +1,5 @@ + + + text.html.markdown - meta.frontmatter - meta.disable-markdown - markup.critic - meta.code-fence - markup.raw - markup.kbd + Markdown Critic Deletion + \ No newline at end of file diff --git a/snippets/Critic Highlight.sublime-snippet b/snippets/Critic Highlight.sublime-snippet new file mode 100644 index 00000000..6ae1d3d1 --- /dev/null +++ b/snippets/Critic Highlight.sublime-snippet @@ -0,0 +1,5 @@ + + > ${1:comment} <<}]]> + text.html.markdown - meta.frontmatter - meta.disable-markdown - markup.critic - meta.code-fence - markup.raw - markup.kbd + Markdown Critic Highlight + \ No newline at end of file diff --git a/snippets/Critic Substitution.sublime-snippet b/snippets/Critic Substitution.sublime-snippet new file mode 100644 index 00000000..07aa7fd3 --- /dev/null +++ b/snippets/Critic Substitution.sublime-snippet @@ -0,0 +1,5 @@ + + ${1:substitution} ~~}]]> + text.html.markdown - meta.frontmatter - meta.disable-markdown - markup.critic - meta.code-fence - markup.raw - markup.kbd + Markdown Critic Substitution + \ No newline at end of file diff --git a/snippets/Heading 1 (mdh1).sublime-snippet b/snippets/Heading 1 (mdh1).sublime-snippet new file mode 100644 index 00000000..68974d85 --- /dev/null +++ b/snippets/Heading 1 (mdh1).sublime-snippet @@ -0,0 +1,6 @@ + + # ${1:heading 1} + mdh1 + text.html.markdown - meta.frontmatter - meta.disable-markdown - meta.code-fence - markup.raw + Markdown Heading 1 + diff --git a/snippets/Heading 2 (mdh2).sublime-snippet b/snippets/Heading 2 (mdh2).sublime-snippet new file mode 100644 index 00000000..7c70d13c --- /dev/null +++ b/snippets/Heading 2 (mdh2).sublime-snippet @@ -0,0 +1,6 @@ + + ## ${1:heading 2} + mdh2 + text.html.markdown - meta.frontmatter - meta.disable-markdown - meta.code-fence - markup.raw + Markdown Heading 2 + diff --git a/snippets/Heading 3 (mdh3).sublime-snippet b/snippets/Heading 3 (mdh3).sublime-snippet new file mode 100644 index 00000000..5636d602 --- /dev/null +++ b/snippets/Heading 3 (mdh3).sublime-snippet @@ -0,0 +1,6 @@ + + ### ${1:heading 3} + mdh3 + text.html.markdown - meta.frontmatter - meta.disable-markdown - meta.code-fence - markup.raw + Markdown Heading 3 + diff --git a/snippets/Heading 4 (mdh4).sublime-snippet b/snippets/Heading 4 (mdh4).sublime-snippet new file mode 100644 index 00000000..57b55a3e --- /dev/null +++ b/snippets/Heading 4 (mdh4).sublime-snippet @@ -0,0 +1,6 @@ + + #### ${1:heading 4} + mdh4 + text.html.markdown - meta.frontmatter - meta.disable-markdown - meta.code-fence - markup.raw + Markdown Heading 4 + diff --git a/snippets/Heading 5 (mdh5).sublime-snippet b/snippets/Heading 5 (mdh5).sublime-snippet new file mode 100644 index 00000000..c2c71816 --- /dev/null +++ b/snippets/Heading 5 (mdh5).sublime-snippet @@ -0,0 +1,6 @@ + + ##### ${1:heading 5} + mdh5 + text.html.markdown - meta.frontmatter - meta.disable-markdown - meta.code-fence - markup.raw + Markdown Heading 5 + diff --git a/snippets/Heading 6 (mdh6).sublime-snippet b/snippets/Heading 6 (mdh6).sublime-snippet new file mode 100644 index 00000000..354a4740 --- /dev/null +++ b/snippets/Heading 6 (mdh6).sublime-snippet @@ -0,0 +1,6 @@ + + ###### ${1:heading 6} + mdh6 + text.html.markdown - meta.frontmatter - meta.disable-markdown - meta.code-fence - markup.raw + Markdown Heading 6 + diff --git a/snippets/Hyperlink (mdl).sublime-snippet b/snippets/Hyperlink (mdl).sublime-snippet new file mode 100644 index 00000000..7dd62e22 --- /dev/null +++ b/snippets/Hyperlink (mdl).sublime-snippet @@ -0,0 +1,6 @@ + + + mdl + text.html.markdown - meta.frontmatter - meta.disable-markdown - meta.code-fence - markup.raw + Markdown Hyperlink + diff --git a/snippets/Image (mdi).sublime-snippet b/snippets/Image (mdi).sublime-snippet new file mode 100644 index 00000000..cbbf57d6 --- /dev/null +++ b/snippets/Image (mdi).sublime-snippet @@ -0,0 +1,6 @@ + + + mdi + text.html.markdown - meta.frontmatter - meta.disable-markdown - meta.code-fence - markup.raw + Markdown Image + diff --git a/snippets/Keyboard Shortcut (kbd).sublime-snippet b/snippets/Keyboard Shortcut (kbd).sublime-snippet new file mode 100644 index 00000000..4014c09e --- /dev/null +++ b/snippets/Keyboard Shortcut (kbd).sublime-snippet @@ -0,0 +1,6 @@ + + ${1:key}]]> + kbd + text.html.markdown - meta.frontmatter - meta.disable-markdown - meta.code-fence - markup.raw + Markdown Keyboard Shortcut + diff --git a/snippets/Markdown_codeblock_(mdc).sublime-snippet b/snippets/Markdown_codeblock_(mdc).sublime-snippet deleted file mode 100644 index 9575ee28..00000000 --- a/snippets/Markdown_codeblock_(mdc).sublime-snippet +++ /dev/null @@ -1,8 +0,0 @@ - - - mdc - text.html.markdown.multimarkdown, text.html.markdown - Markdown Codeblock - diff --git a/snippets/Markdown_header_(mdh1).sublime-snippet b/snippets/Markdown_header_(mdh1).sublime-snippet deleted file mode 100644 index 8cd84dca..00000000 --- a/snippets/Markdown_header_(mdh1).sublime-snippet +++ /dev/null @@ -1,7 +0,0 @@ - - - mdh1 - text.html.markdown.multimarkdown, text.html.markdown - Markdown Header 1 - diff --git a/snippets/Markdown_header_(mdh2).sublime-snippet b/snippets/Markdown_header_(mdh2).sublime-snippet deleted file mode 100644 index f98fc387..00000000 --- a/snippets/Markdown_header_(mdh2).sublime-snippet +++ /dev/null @@ -1,7 +0,0 @@ - - - mdh2 - text.html.markdown.multimarkdown, text.html.markdown - Markdown Header 2 - diff --git a/snippets/Markdown_header_(mdh3).sublime-snippet b/snippets/Markdown_header_(mdh3).sublime-snippet deleted file mode 100644 index a8d5cb08..00000000 --- a/snippets/Markdown_header_(mdh3).sublime-snippet +++ /dev/null @@ -1,7 +0,0 @@ - - - mdh3 - text.html.markdown.multimarkdown, text.html.markdown - Markdown Header 3 - diff --git a/snippets/Markdown_image_(mdi).sublime-snippet b/snippets/Markdown_image_(mdi).sublime-snippet deleted file mode 100644 index b5c3c4e9..00000000 --- a/snippets/Markdown_image_(mdi).sublime-snippet +++ /dev/null @@ -1,6 +0,0 @@ - - - mdi - text.html.markdown.multimarkdown, text.html.markdown - Markdown Image - diff --git a/snippets/Markdown_link_(mdl).sublime-snippet b/snippets/Markdown_link_(mdl).sublime-snippet deleted file mode 100644 index c246e648..00000000 --- a/snippets/Markdown_link_(mdl).sublime-snippet +++ /dev/null @@ -1,6 +0,0 @@ - - - mdl - text.html.markdown.multimarkdown, text.html.markdown - Markdown Hyperlink - diff --git a/switch_list_bullet_type.py b/switch_list_bullet_type.py deleted file mode 100644 index 9c3555ca..00000000 --- a/switch_list_bullet_type.py +++ /dev/null @@ -1,43 +0,0 @@ -import sublime_plugin -import re -try: - from MarkdownEditing.mdeutils import * -except ImportError: - from mdeutils import * - - -class SwitchListBulletTypeCommand(MDETextCommand): - - def run(self, edit): - todo = [] - unordered_bullets = self.view.settings().get("mde.list_indent_bullets", ["*", "-", "+"]) - for region in self.view.sel(): - lines = self.view.line(region) - lines = self.view.split_by_newlines(lines) - number = 1 - for line in lines: - line_content = self.view.substr(line) - # print(line_content) - m = re.match(r"^(\s*(?:>\s*)?)[" + - ''.join(re.escape(i) for i in unordered_bullets) + - r"](\s+.*)$", line_content) - if m: - # Transform the bullet to numbered bullet type - new_line = m.group(1) + str(number) + "." + m.group(2) - if self.view.settings().get('mde.auto_increment_ordered_list_number', True): - number += 1 - - # Insert the new item - todo.append([line, new_line]) - else: - m = re.match(r"^(\s*(?:>\s*)?)[0-9]+\.(\s+.*)$", line_content) - if m: - # Transform the bullet to unnumbered bullet type - new_line = m.group(1) + unordered_bullets[0] + m.group(2) - - # Insert the new item - todo.append([line, new_line]) - - while len(todo) > 0: - j = todo.pop() - self.view.replace(edit, j[0], j[1]) diff --git a/Indent%3A Raw.tmPreferences b/syntaxes/Indentation Rules.tmPreferences similarity index 51% rename from Indent%3A Raw.tmPreferences rename to syntaxes/Indentation Rules.tmPreferences index a5e2bd09..1a2054f5 100644 --- a/Indent%3A Raw.tmPreferences +++ b/syntaxes/Indentation Rules.tmPreferences @@ -1,11 +1,8 @@ - - name - Indent: Raw Block scope - markup.raw.block.markdown + text.html.markdown markup.raw settings decreaseIndentPattern @@ -13,7 +10,5 @@ increaseIndentPattern ^.*(\{[^}"']*|\([^)"']*)$ - uuid - E23C5DD2-9A36-4B4A-9729-2A769A055B92 diff --git a/syntaxes/Markdown.sublime-settings b/syntaxes/Markdown.sublime-settings new file mode 100644 index 00000000..29c7779c --- /dev/null +++ b/syntaxes/Markdown.sublime-settings @@ -0,0 +1,3 @@ +{ + "trim_trailing_white_space_on_save": false +} diff --git a/syntaxes/Markdown.sublime-syntax b/syntaxes/Markdown.sublime-syntax new file mode 100644 index 00000000..dbaa4ff9 --- /dev/null +++ b/syntaxes/Markdown.sublime-syntax @@ -0,0 +1,2678 @@ +%YAML 1.2 +--- +# http://www.sublimetext.com/docs/3/syntax.html +name: Markdown +file_extensions: + - md + - mdown + - markdown + - markdn +scope: text.html.markdown +comment: |- + this definition aims to meet CommonMark specifications http://spec.commonmark.org/ + with GitHub Formatted Markdown extensions https://github.github.com/gfm/ + and has a few extras like Markdown Extra's footnotes https://michelf.ca/projects/php-markdown/extra/#footnotes + the scope suffix should indicate which flavor of Markdown the feature came from, to help make this syntax definition easier to maintain +variables: + thematic_break: |- + (?x: + [ ]{,3} # between 0 to 3 spaces + (?: # followed by one of the following: + [-](?:[ ]{,2}[-]){2,} # - a dash, followed by the following at least twice: between 0 to 2 spaces followed by a dash + | [*](?:[ ]{,2}[*]){2,} # - a star, followed by the following at least twice: between 0 to 2 spaces followed by a star + | [_](?:[ ]{,2}[_]){2,} # - an underscore, followed by the following at least twice: between 0 to 2 spaces followed by an underscore + ) + [ \t]*$ # followed by any number of tabs or spaces, followed by the end of the line + ) + block_quote: (?:[ ]{,3}(>)[ ]?) # between 0 and 3 spaces, followed by a greater than sign, (followed by any character or the end of the line = "only care about optional space!") + atx_heading: (?:[ ]{,3}[#]{1,6}(?:[ \t]|$)) # between 0 and 3 spaces, followed 1 to 6 hashes, followed by at least one space or tab or by end of the line + atx_heading_space: (?:(?=[ \t]+#+[ \t]*$)|[ \t]+|$) # consume spaces only if heading is not empty to ensure `atx_heading_end` can fully match closing hashes + atx_heading_end: (?:[ \t]+(#+))?[ \t]*($\n?) # \n is optional so ## is matched as end punctuation in new document (at eof) + setext_escape: ^(?=[ ]{,3}(?:=+|-+)\s*$) # between 0 and 3 spaces, followed by at least one hyphon or equal sign (setext underline can be of any length) + indented_code_block: (?:[ ]{4}|\t) # 4 spaces or a tab + list_item: (?:[ ]{,3}(?:\d+[.)]|[*+-])\s) # between 0 and 3 spaces, followed by either: at least one integer and a full stop or a parenthesis, or (a star, plus or dash), followed by whitespace + escape: '\\[-`*_#+.!(){}\[\]\\>|~<]' + backticks: |- + (?x: + (`{4})(?![\s`])(?:[^`]+(?=`)|(?!`{4})`+(?!`))+(`{4})(?!`) # 4 backticks, followed by at least one non whitespace, non backtick character, followed by (less than 4 backticks, or at least one non backtick character) at least once, followed by exactly 4 backticks + | (`{3})(?![\s`])(?:[^`]+(?=`)|(?!`{3})`+(?!`))+(`{3})(?!`) # 3 backticks, followed by at least one non whitespace, non backtick character, followed by (less than 3 backticks, or at least one non backtick character) at least once, followed by exactly 3 backticks + | (`{2})(?![\s`])(?:[^`]+(?=`)|(?!`{2})`+(?!`))+(`{2})(?!`) # 2 backticks, followed by at least one non whitespace, non backtick character, followed by (less than 2 backticks, or at least one non backtick character) at least once, followed by exactly 2 backticks + | (`{1})(?![\s`])(?:[^`]+(?=`)|(?!`{1})`+(?!`))+(`{1})(?!`) # 1 backtick, followed by at least one non whitespace, non backtick character, followed by ( at least one non backtick character) at least once, followed by exactly 1 backtick + ) + balance_square_brackets: |- + (?x: + (?: + {{escape}}+ # escape characters + | [^\[\]`\\]+(?=[\[\]`\\]|$) # anything that isn't a square bracket or a backtick or the start of an escape character + | {{backticks}} # inline code + | \[(?: # nested square brackets (one level deep) + [^\[\]`]+(?=[\[\]`]) # anything that isn't a square bracket or a backtick + {{backticks}}? # balanced backticks + )*\] # closing square bracket + )+ # at least one character + ) + html_entity: '&([a-zA-Z0-9]+|#\d+|#x\h+);' + skip_html_tags: (?:<[^>]+>) + balance_square_brackets_and_emphasis: |- + (?x: + (?: + {{escape}}+ # escape characters + | [^\[\]`\\_*]+(?=[\[\]`\\_*]|$) # anything that isn't a square bracket, a backtick, the start of an escape character, or an emphasis character + | {{backticks}} # inline code + | \[(?: # nested square brackets (one level deep) + [^\[\]`]+(?=[\[\]`]) # anything that isn't a square bracket or a backtick + {{backticks}}? # balanced backticks + )*\] # closing square bracket + )+ # at least one character + ) + balance_square_brackets_pipes_and_emphasis: |- + (?x: + (?: + {{escape}}+ # escape characters + | [^\[\]`\\_*|]+(?=[\[\]`\\_*|]|$) # anything that isn't a square bracket, a backtick, the start of an escape character, or an emphasis character + | {{backticks}} # inline code + | \[(?: # nested square brackets (one level deep) + [^\[\]`]+(?=[\[\]`]) # anything that isn't a square bracket or a backtick + {{backticks}}? # balanced backticks + )*\] # closing square bracket + )+ # at least one character + ) + balanced_emphasis: |- + (?x: + \* (?!\*){{balance_square_brackets_and_emphasis}}+\* (?!\*) + | \*\* {{balance_square_brackets_and_emphasis}}+\*\* + | _ (?!_) {{balance_square_brackets_and_emphasis}}+_ (?!_) + | __ {{balance_square_brackets_and_emphasis}}+__ + ) + balanced_table_cell: |- # Pipes inside other inline spans (such as emphasis, code, etc.) will not break a cell, emphasis in table cells can't span multiple lines + (?x: + (?: + {{balance_square_brackets_pipes_and_emphasis}} + | {{balanced_emphasis}} + )+ # at least one character + ) + table_first_row: |- + (?x: + # at least 2 non-escaped pipe chars on the line + (?:{{balanced_table_cell}}?\|){2} + + # something other than whitespace followed by a pipe char or hyphon, + # followed by something other than whitespace and the end of the line + | (?! \s*\-\s+ | \s+\|){{balanced_table_cell}}\|(?!\s+$) + ) + fenced_code_block_start: |- + (?x: + ([ \t]*) + ( + (`){3,} # 3 or more backticks + (?![^`]*`) # not followed by any more backticks on the same line + | # or + (~){3,} # 3 or more tildas + (?![^~]*~) # not followed by any more tildas on the same line + ) + \s* # allow for whitespace between code block start and info string + ) + fenced_code_block_language: |- + (?x: # first word of an infostring is used as language specifier + ( + [[:alpha:]] # starts with a letter to make sure not to hit any attribute annotation + [^`\s]* # optionally followed by any nonwhitespace character (except backticks) + ) + ) + fenced_code_block_trailing_infostring_characters: |- + (?x: + ( + \s* # any whitespace, or .. + | + \s[^`]* # any characters (except backticks), separated by whitespace ... + ) + $\n? # ... until EOL + ) + code_fence_escape: ^{{code_fence_end}} + code_fence_end: |- + (?x: + [ \t]* + ( + \2 # the backtick/tilde combination that opened the code fence + (?:\3|\4)* # plus optional additional closing characters + ) + \s*$ # any amount of whitespace until EOL + ) + html_tag_open_commonmark: |- + (?xi: + < + [a-z] # A tag name consists of an ASCII letter + [a-z0-9-]* # followed by zero or more ASCII letters, digits, or hyphens (-) + (?: # An attribute consists of whitespace, an attribute name, and an optional attribute value specification + \s+ + [a-z_:] # An attribute name consists of an ASCII letter, _, or : + [a-z0-9_.:-]* # followed by zero or more ASCII letters, digits, _, ., :, or - + (?: # An attribute value specification consists of optional whitespace, a = character, optional whitespace, and an attribute value + \s* + = + \s* + (?: + [^ @'=<>`]+ # An unquoted attribute value is a nonempty string of characters not including spaces, ", ', =, <, >, or ` + | '[^']*' # A single-quoted attribute value consists of ', zero or more characters not including ', and a final ' + | "[^"]*" # A double-quoted attribute value consists of ", zero or more characters not including ", and a final " + ) + )? + )* + \s* + /? + > + ) + html_tag_close_commonmark: |- + (?xi: + + ) + html_tag_block_end_at_close_tag: |- + (?xi: + (script|style|pre)\b + ) + html_tag_block_end_at_blank_line: |- + (?x: + /? + (?i:address|article|aside|base|basefont|blockquote|body|caption|center|col|colgroup|dd|details|dialog|dir|div|dl|dt|fieldset|figcaption|figure|footer|form|frame|frameset|h1|h2|h3|h4|h5|h6|head|header|hr|html|iframe|legend|li|link|main|menu|menuitem|meta|nav|noframes|ol|optgroup|option|p|param|section|source|summary|table|tbody|td|tfoot|th|thead|title|tr|track|ul) + (?:\s|$|/?>) + ) + ascii_space: '\t\n\f ' + tag_attribute_name_start: (?=[^{{ascii_space}}=/>}]) + tag_attribute_name_break: (?=[{{ascii_space}}=/>}]) + tag_unquoted_attribute_start: (?=[^{{ascii_space}}=/>}]) + tag_unquoted_attribute_break: (?=[{{ascii_space}}}]|/?>) + +contexts: + + main: + - include: frontmatter + - match: '' + set: markdown + + frontmatter: + - match: (---)\s*(?i:(coffee)\s*)\n + captures: + 0: meta.frontmatter.markdown + 1: punctuation.section.block.begin.frontmatter.markdown + 2: constant.other.language-name.markdown + embed: scope:source.coffee + embed_scope: meta.frontmatter.markdown source.coffee.embedded.markdown + escape: ^(---|\.{3})\s*\n # pandoc requires the remainder of the line to be blank + escape_captures: + 0: meta.frontmatter.markdown + 1: punctuation.section.block.end.frontmatter.markdown + - match: (---)\s*(?i:(json)\s*)\n + captures: + 0: meta.frontmatter.markdown + 1: punctuation.section.block.begin.frontmatter.markdown + 2: constant.other.language-name.markdown + embed: scope:source.json + embed_scope: meta.frontmatter.markdown source.json.embedded.markdown + escape: ^(---|\.{3})\s*\n # pandoc requires the remainder of the line to be blank + escape_captures: + 0: meta.frontmatter.markdown + 1: punctuation.section.block.end.frontmatter.markdown + - match: (---)\s*(?i:(yaml)\s*)?\n + captures: + 0: meta.frontmatter.markdown + 1: punctuation.section.block.begin.frontmatter.markdown + 2: constant.other.language-name.markdown + embed: scope:source.yaml + embed_scope: meta.frontmatter.markdown source.yaml.embedded.markdown + escape: ^(---|\.{3})\s*\n # pandoc requires the remainder of the line to be blank + escape_captures: + 0: meta.frontmatter.markdown + 1: punctuation.section.block.end.frontmatter.markdown + + markdown: + - match: |- + (?x)^ + (?= {{block_quote}} + | {{indented_code_block}}(?!$) + | {{atx_heading}} + | {{thematic_break}} + | {{table_first_row}} + ) + comment: | + We could also use an empty end match and set + applyEndPatternLast, but then we must be sure that the begin + pattern will only match stuff matched by the sub-patterns. + push: + - meta_scope: meta.block-level.markdown + - include: block-quotes + - include: ligatures + - include: indented-code-block + - include: atx-heading + - include: thematic-break + - include: table + - include: immediately-pop + - match: ^([ ]{0,3})([*+-])( (\[)([ xX])(\]))?(?=\s) + captures: + 1: markup.list.unnumbered.markdown + 2: markup.list.unnumbered.bullet.markdown punctuation.definition.list_item.markdown + 3: markup.list.unnumbered.markdown + 4: markup.checkbox.begin.markdown-gfm punctuation.definition.checkbox.begin.markdown-gfm + 5: markup.checkbox.mark.markdown-gfm + 6: markup.checkbox.end.markdown-gfm punctuation.definition.checkbox.end.markdown-gfm + push: + - meta_content_scope: markup.list.unnumbered.markdown + - match: ^(?=\S) + pop: true + - include: list-paragraph + - match: ^([ ]{0,3})(\d+([.)]))(?=\s) + captures: + 1: markup.list.numbered.markdown + 2: markup.list.numbered.bullet.markdown + 3: punctuation.definition.list_item.markdown + push: + - meta_content_scope: markup.list.numbered.markdown + - match: ^(?=\S) + pop: true + - include: list-paragraph + - match: '^[ ]{0,3}(?=<((?i:pre))\b)' + comment: Markdown formatting is disabled inside block-level tags. + push: [disabled-markdown-pop-at-eol, disable-markdown-pop-at-tag] + - match: '^[ ]{0,3}(?=<{{html_tag_block_end_at_close_tag}})' + comment: Markdown formatting is disabled inside block-level tags. + push: [disabled-markdown-pop-at-eol, disable-markdown-pop-after-tag] + - match: '^[ ]{0,3}(?=<\?)' + comment: Markdown formatting is disabled inside preprocessor instructions. + push: [disabled-markdown-pop-at-eol, disable-markdown-pop-at-php] + - match: '^[ ]{0,3}(?=?' # <- <-- <--- <-> <--> <---> + # <= <== <=== <=> <==> <===> + - match: '>(-+|=+)[<>]?' # >- >-- >--- >-> >--> >---> >-< >--< >---< + # >= >== >=== >=> >==> >===> >=< >==< >===< + - match: '<<+|<>|>>+' # << <<< <<<< <> >>>> >>> >> + + block-quotes: + # https://spec.commonmark.org/0.30/#block-quotes + - match: ^{{block_quote}} + comment: |- + We terminate the block quote when seeing an empty line, a + separator or a line with leading > characters. The latter is + to “reset” the quote level for quoted lines. + The idea here is to match block level elements first, then once + we have confirmed there are no block level elements left, move to + matching inline markdown. This prevents block level elements being + detected when they shouldn't be. + captures: + 1: punctuation.definition.blockquote.markdown + push: + - block-quote-meta + - block-quote-content + + block-quote-nested: + - match: '{{block_quote}}' + captures: + 1: punctuation.definition.blockquote.markdown + set: + - block-quote-meta + - block-quote-content + + block-quote-meta: + - meta_scope: markup.quote.markdown + - include: immediately-pop + + block-quote-content: + - include: block-quote-nested + - include: block-quote-code-block + - include: block-quote-list-item + - include: atx-heading + - include: indented-code-block + - include: thematic-break + - match: '' + set: block-quote-text + + block-quote-code-block: + - match: |- + (?x) + {{fenced_code_block_start}} + {{fenced_code_block_language}}? + .*$\n? # all characters until EOL + captures: + 0: meta.code-fence.definition.begin.text.markdown-gfm + 2: punctuation.definition.raw.code-fence.begin.markdown + 5: constant.other.language-name.markdown + set: block-quote-code-block-content + + block-quote-code-block-content: + - match: ^(?!\s*{{block_quote}}) + pop: true + - match: '{{code_fence_end}}' + captures: + 0: meta.code-fence.definition.end.text.markdown-gfm + 1: punctuation.definition.raw.code-fence.end.markdown + pop: true + - match: '{{block_quote}}' + captures: + 1: punctuation.definition.blockquote.markdown + - match: '' + push: block-quote-code-block-text + + block-quote-code-block-text: + - meta_content_scope: markup.raw.code-fence.markdown-gfm + - match: ^ + pop: true + + block-quote-list-item: + - match: ([ ]{,3})(\d+([.)]))(\s) + captures: + 1: markup.list.numbered.markdown + 2: markup.list.numbered.bullet.markdown + 3: punctuation.definition.list_item.markdown + 4: markup.list.numbered.markdown + set: + - block-quote-ordered-list-content + - list-content + - match: ([ ]{,3})([*+-])((?:[ ](\[)([ xX])(\]))?\s) + captures: + 1: markup.list.unnumbered.markdown + 2: markup.list.unnumbered.bullet.markdown punctuation.definition.list_item.markdown + 3: markup.list.unnumbered.markdown + 4: markup.checkbox.begin.markdown-gfm punctuation.definition.checkbox.begin.markdown-gfm + 5: markup.checkbox.mark.markdown-gfm + 6: markup.checkbox.end.markdown-gfm punctuation.definition.checkbox.end.markdown-gfm + set: + - block-quote-unordered-list-content + - list-content + + block-quote-ordered-list-content: + - meta_content_scope: markup.list.numbered.markdown meta.paragraph.list.markdown + - include: block-quote-text + + block-quote-unordered-list-content: + - meta_content_scope: markup.list.unnumbered.markdown meta.paragraph.list.markdown + - include: block-quote-text + + block-quote-text: + - match: |- + (?x) + ^ + (?= \s*$ + | {{atx_heading}} + | {{block_quote}} + | {{fenced_code_block_start}} + | {{list_item}} + | {{thematic_break}} + ) + pop: true + - include: inline-bold-italic-linebreak + - include: tag-kbd + - include: scope:text.html.basic + + indented-code-block: + - match: '{{indented_code_block}}.*$\n?' + scope: markup.raw.block.markdown + + bold: + - include: ligatures + - match: '(\*\*)(\*)(?=\S)(?!\*)' + captures: + 1: punctuation.definition.bold.begin.markdown + 2: markup.italic.markdown punctuation.definition.italic.begin.markdown + push: + - meta_scope: markup.bold.markdown + - meta_content_scope: markup.italic.markdown + - match: |- + (?x) + [ \t]*\*{4,} # if there are more than 3 its not applicable to be bold or italic + | [ \t]+\*(?!\*) # whitespace followed by 1 is also not applicable (but whitespace followed by 2 could be bold punctuation) + | ^\*(?!\*) # emphasis can't be closed at the start of the line + - match: (\*)(\*\*) + captures: + 1: markup.italic.markdown punctuation.definition.italic.end.markdown + 2: punctuation.definition.bold.end.markdown + pop: true + - match: \*\* + scope: punctuation.definition.bold.end.markdown + set: + - meta_content_scope: markup.italic.markdown + - match: |- + (?x) + [ \t]*\*{3,} # if there are more than 3 its not applicable to be bold or italic + | [ \t]+\*\*+ # whitespace followed by 1 is also not applicable (but whitespace followed by 2 could be bold punctuation) + | ^\*\* # emphasis can't be closed at the start of the line + - match: \* + scope: markup.italic.markdown punctuation.definition.italic.end.markdown + pop: true + - include: format-common + - include: bold + - include: strikethrough + - match: \* + scope: punctuation.definition.italic.end.markdown + set: + - meta_content_scope: markup.bold.markdown + - match: |- + (?x) + [ \t]*\*{3,} # if there are more than 3 its not applicable to be bold or italic + | [ \t]+\*\*+ # whitespace followed by 1 is also not applicable (but whitespace followed by 2 could be bold punctuation) + | ^\*\* # emphasis can't be closed at the start of the line + - match: \*\* + scope: markup.bold.markdown punctuation.definition.bold.end.markdown + pop: true + - include: format-common + - include: italic + - include: strikethrough + - include: format-common + - include: strikethrough + - match: '\*\*(?=\S)(?!\*\*|\*\s)' + scope: punctuation.definition.bold.begin.markdown + push: + - meta_scope: markup.bold.markdown + - match: |- + (?x) + [ \t]*\*{4,} # if there are more than 3 its not applicable to be bold or italic + | [ \t]+\*\*+ # whitespace followed by 2 or more is also not applicable + | ^\*\* # emphasis can't be closed at the start of the line + - match: (?:_)?(\*\*) + captures: + 1: punctuation.definition.bold.end.markdown + pop: true + # Consume the underscore that has no corresponding underscore before the closing bold + # punctuation on the same line, as it won't be treated as italic by CommonMark + - match: \b_(?=[^\s_])(?=[^*_]*\*\*) + - include: format-common + - include: italic + - include: strikethrough + - match: '\b(__)(_)(?=\S)(?!_)' + captures: + 1: punctuation.definition.bold.begin.markdown + 2: markup.italic.markdown punctuation.definition.italic.begin.markdown + push: + - meta_scope: markup.bold.markdown + - meta_content_scope: markup.italic.markdown + - match: |- + (?x) + [ \t]*_{4,} # if there are more than 3 its not applicable to be bold or italic + | [ \t]+_(?!_) # whitespace followed by 1 is also not applicable (but whitespace followed by 2 could be bold punctuation) + | ^_(?!_) # emphasis can't be closed at the start of the line + - match: (_)(__)\b + captures: + 1: markup.italic.markdown punctuation.definition.italic.end.markdown + 2: punctuation.definition.bold.end.markdown + pop: true + - match: _\b + scope: punctuation.definition.italic.end.markdown + set: + - meta_content_scope: markup.bold.markdown + - match: |- + (?x) + [ \t]*_{3,} # if there are more than 3 its not applicable to be bold or italic + | [ \t]+__+ # whitespace followed by 1 is also not applicable (but whitespace followed by 2 could be bold punctuation) + | ^__ # emphasis can't be closed at the start of the line + - match: __\b + scope: markup.bold.markdown punctuation.definition.bold.end.markdown + pop: true + - include: format-common + - include: italic + - include: strikethrough + - match: __\b + scope: punctuation.definition.bold.end.markdown + set: + - meta_content_scope: markup.italic.markdown + - match: |- + (?x) + [ \t]*_{3,} # if there are more than 3 its not applicable to be bold or italic + | [ \t]+__+ # whitespace followed by 1 is also not applicable (but whitespace followed by 2 could be bold punctuation) + | ^__ # emphasis can't be closed at the start of the line + - match: _\b + scope: markup.italic.markdown punctuation.definition.italic.end.markdown + pop: true + - include: format-common + - include: bold + - include: strikethrough + - include: format-common + - include: strikethrough + - match: '\b__(?=\S)(?!_[_\s])' + scope: punctuation.definition.bold.begin.markdown + push: + - meta_scope: markup.bold.markdown + - match: |- + (?x) + [ \t]*_{4,} # if there are more than 3 its not applicable to be bold or italic + | [ \t]+__+ # whitespace followed by 2 or more is also not applicable + | ^__ # emphasis can't be closed at the start of the line + - match: (?:\*)?(__\b) + captures: + 1: punctuation.definition.bold.end.markdown + pop: true + # Consume the asterisk that has no corresponding asterisk before the closing bold + # punctuation on the same line, as it won't be treated as italic by CommonMark + - match: \*(?=[^\s*])(?=[^*_]*__\b) + - include: format-common + - include: italic + - include: strikethrough + + bracket: + - match: '<(?![A-Za-z/?!$])' + comment: | + Markdown will convert this for us. We match it so that the + HTML grammar will not mark it up as invalid. + scope: meta.other.valid-bracket.markdown + + escape: + - match: '{{escape}}' + scope: constant.character.escape.markdown + + atx-heading: + # https://spec.commonmark.org/0.30/#atx-headings + # Note: + # Consume spaces and tabs after opening hashes so entity.name + # starts with first non-whitespace character, + # but don't do so if directly followed by closing hashes + # as terminator pattern requires them to match then. + - match: '[ ]{,3}(#{1}){{atx_heading_space}}' + captures: + 1: punctuation.definition.heading.begin.markdown + push: atx-heading1-content + - match: '[ ]{,3}(#{2}){{atx_heading_space}}' + captures: + 1: punctuation.definition.heading.begin.markdown + push: atx-heading2-content + - match: '[ ]{,3}(#{3}){{atx_heading_space}}' + captures: + 1: punctuation.definition.heading.begin.markdown + push: atx-heading3-content + - match: '[ ]{,3}(#{4}){{atx_heading_space}}' + captures: + 1: punctuation.definition.heading.begin.markdown + push: atx-heading4-content + - match: '[ ]{,3}(#{5}){{atx_heading_space}}' + captures: + 1: punctuation.definition.heading.begin.markdown + push: atx-heading5-content + - match: '[ ]{,3}(#{6}){{atx_heading_space}}' + captures: + 1: punctuation.definition.heading.begin.markdown + push: atx-heading6-content + + atx-heading1-content: + - meta_scope: markup.heading.1.markdown + - meta_content_scope: entity.name.section.markdown + - include: atx-heading-content + + atx-heading2-content: + - meta_scope: markup.heading.2.markdown + - meta_content_scope: entity.name.section.markdown + - include: atx-heading-content + + atx-heading3-content: + - meta_scope: markup.heading.3.markdown + - meta_content_scope: entity.name.section.markdown + - include: atx-heading-content + + atx-heading4-content: + - meta_scope: markup.heading.4.markdown + - meta_content_scope: entity.name.section.markdown + - include: atx-heading-content + + atx-heading5-content: + - meta_scope: markup.heading.5.markdown + - meta_content_scope: entity.name.section.markdown + - include: atx-heading-content + + atx-heading6-content: + - meta_scope: markup.heading.6.markdown + - meta_content_scope: entity.name.section.markdown + - include: atx-heading-content + + atx-heading-content: + - match: '{{atx_heading_end}}' + captures: + 1: punctuation.definition.heading.end.markdown + 2: meta.whitespace.newline.markdown + pop: true + - include: inline-bold-italic + + image-inline: + - match: |- + (?x: + (\!\[) # Images start with ![ + (?= {{balance_square_brackets}}? # balanced square brackets, backticks, taking into account escapes etc. + \] # Closing square bracket + [ ]? # Space not allowed, but we check for it anyway to mark it as invalid + \( # Open paren + ) + ) + captures: + 1: meta.image.inline.markdown punctuation.definition.image.begin.markdown + push: [image-inline-attr, image-inline-after-text, image-link-text] + + image-link-text: + - meta_content_scope: meta.image.inline.description.markdown + - include: link-text + - match: \] + scope: meta.image.inline.markdown punctuation.definition.image.end.markdown + pop: true + + image-inline-after-text: + - match: '([ ]*)(\()' # spaces not allowed before the open paren, but we check for it anyway to mark it as invalid + captures: + 1: invalid.illegal.whitespace.markdown + 2: punctuation.definition.metadata.begin.markdown + set: + - meta_scope: meta.image.inline.markdown + - match: \) + scope: punctuation.definition.metadata.end.markdown + pop: true + - match: <(?=[^>)]*>) + scope: punctuation.definition.link.begin.markdown + push: + - meta_content_scope: markup.underline.link.image.markdown + - match: \> + scope: punctuation.definition.link.end.markdown + set: link-title + - match: \s+ + scope: invalid.illegal.unexpected-whitespace.markdown + - match: (?=\S) + set: + - meta_scope: meta.image.inline.markdown + - match: '[^\s)]+' + scope: markup.underline.link.image.markdown + - match: \) + scope: punctuation.definition.metadata.end.markdown + pop: true + - match: (?!\n)\s+(?!\s*(?:[)('"]|$)) + scope: invalid.illegal.unexpected-whitespace.markdown + - match: (?=\s*(?!\))) + push: link-title + + image-inline-attr: + - match: '([ ]*)(\{)(?=[^}]*\})' + captures: + 1: invalid.illegal.whitespace.markdown + 2: punctuation.definition.attributes.begin.markdown + set: + - meta_scope: meta.image.inline.markdown + - include: tag-attributes + - include: immediately-pop + + image-ref: + - match: |- + (?x: + (\!\[) # Images start with ![ + (?= {{balance_square_brackets}}? # balanced square brackets, backticks, taking into account escapes etc. + \] # Closing square bracket + [ ]? # Space + \[ # [ + [^\]]+ # anything other than ] + \] # ] + ) + ) + captures: + 1: meta.image.reference.markdown punctuation.definition.image.begin.markdown + push: [image-ref-attr, image-ref-after-text, image-ref-text] + + image-ref-text: + - meta_content_scope: meta.image.reference.description.markdown + - include: link-text + - match: \] + scope: meta.image.reference.markdown punctuation.definition.image.end.markdown + pop: true + + image-ref-after-text: + - match: '[ ]?(\[)([^\]]+)(\])' + captures: + 1: punctuation.definition.constant.begin.markdown + 2: constant.other.reference.link.markdown + 3: punctuation.definition.constant.end.markdown + scope: meta.image.reference.markdown + pop: true + + image-ref-attr: + - match: '([ ]*)(\{)(?=[^}]*\})' + captures: + 1: invalid.illegal.whitespace.markdown + 2: punctuation.definition.attributes.begin.markdown + set: + - meta_scope: meta.image.reference.markdown + - include: tag-attributes + - include: immediately-pop + + inline: + - include: escape + - include: ampersand + - include: critic-inline + - include: ligatures + - include: bracket + - include: code-span + - include: image-inline + - include: link-inline + - include: autolink-inet + - include: autolink-email + - include: image-ref + - include: link-ref-wiki + - include: link-ref-footnote + - include: link-ref-literal + - include: link-ref + + inline-bold-italic: + - include: inline + - include: bold + - include: italic + - include: strikethrough + + inline-bold-italic-linebreak: + - include: inline-bold-italic + - include: hard-line-break + + italic: + - match: '\*(?=\S)(?!\*)' + scope: punctuation.definition.italic.begin.markdown + push: + - meta_scope: markup.italic.markdown + - match: |- + (?x) + [ \t]*\*{4,} # if there are more than 3 its not applicable to be bold or italic + | [ \t]+\*(?!\*) # whitespace followed by 1 is also not applicable (but whitespace followed by 2 could be bold punctuation) + | ^\*(?!\*) # emphasis can't be closed at the start of the line + - match: \*(?!\*[^*]) + scope: punctuation.definition.italic.end.markdown + pop: true + - match: \*+ + - include: format-common + - include: bold + - include: strikethrough + - match: '\b_(?=\S)(?!_)' + scope: punctuation.definition.italic.begin.markdown + push: + - meta_scope: markup.italic.markdown + - match: |- + (?x) + [ \t]*_{4,} # if there are more than 3 its not applicable to be bold or italic + | [ \t]+_(?!_) # whitespace followed by 1 is also not applicable (but whitespace followed by 2 could be bold punctuation) + | ^_(?!_) # emphasis can't be closed at the start of the line + - match: _\b + scope: punctuation.definition.italic.end.markdown + pop: true + - include: format-common + - include: bold + - include: strikethrough + - match: '[*_]+' + + strikethrough: + - match: (?:~(?!~}|>|\s))+ # any number of ~ up to ~> or ~~} critic markers + scope: punctuation.definition.strikethrough.begin.markdown + push: strikethrough-content + + strikethrough-content: + - meta_scope: markup.strikethrough.markdown-gfm + - match: (?:~(?!~}|>))+ # any number of ~ up to ~> or ~~} critic markers + scope: punctuation.definition.strikethrough.end.markdown + pop: true + - include: format-common + - include: bold + - include: italic + + format-common: + - match: '{{setext_escape}}' + pop: true + - match: ^\s*$\n? + scope: invalid.illegal.non-terminated.bold-italic.markdown + pop: true + - include: paragraph-end + - include: hard-line-break + - include: inline + - include: tag-kbd + - include: scope:text.html.basic + + hard-line-break: + - match: '[ ]{2,}$' + scope: meta.hard-line-break.markdown punctuation.definition.hard-line-break.markdown + - match: '(\\)$\n' + scope: meta.hard-line-break.markdown + captures: + 1: constant.character.escape.markdown + + autolink-email: + - match: '(<)((?:mailto:)?[-+.\w]+@[-a-z0-9]+(\.[-a-z0-9]+)*\.[a-z]+)(>)' + scope: meta.link.email.lt-gt.markdown + captures: + 1: punctuation.definition.link.begin.markdown + 2: markup.underline.link.markdown + 4: punctuation.definition.link.end.markdown + - match: '[\w.+-]+@[\w-]+(\.((?![._-][\W])[\w_-])+)+(?![_-])' + scope: markup.underline.link.markdown + + autolink-inet: + - match: (<)((?:https?|ftp)://.*?)(>) + scope: meta.link.inet.markdown + captures: + 1: punctuation.definition.link.begin.markdown + 2: markup.underline.link.markdown + 3: punctuation.definition.link.end.markdown + - match: (((https|http|ftp)://)|www\.)[\w-]+(\.[\w-]+)+ + scope: markup.underline.link.markdown-gfm + push: # After a valid domain, zero or more non-space non-< characters may follow + - match: (?=[?!.,:*_~]*(?:[\s<]|$)) # Trailing punctuation (specifically, ?, !, ., ,, :, *, _, and ~) will not be considered part of the autolink, though they may be included in the interior of the link + pop: true + - match: (?={{html_entity}}[?!.,:*_~]*[\s<]) # If an autolink ends in a semicolon (;), we check to see if it appears to resemble an entity reference; if the preceding text is & followed by one or more alphanumeric characters. If so, it is excluded from the autolink + pop: true + - match: \( # When an autolink ends in ), we scan the entire autolink for the total number of parentheses. If there is a greater number of closing parentheses than opening ones, we don’t consider the last character part of the autolink, in order to facilitate including an autolink inside a parenthesis + push: + - meta_scope: markup.underline.link.markdown-gfm + - match: (?=[?!.,:*_~]*[\s<]) + pop: true + - match: \) + pop: true + - match: (?=\)[?!.,:*_~]*[\s<]) + pop: true + - match: '[^?!.,:*_~\s<&()]+|\S' + scope: markup.underline.link.markdown-gfm + + link-inline: + - match: |- + (?x: + (\[) + (?= + {{balance_square_brackets}}? + \] + [ ]?\( + ) + ) + captures: + 1: meta.link.inline.markdown punctuation.definition.link.begin.markdown + push: [link-inline-attr, link-inline-after-text, link-inline-link-text] + + link-inline-after-text: + - match: '([ ]*)(\()' # spaces not allowed before the open paren, but we check for it anyway to mark it as invalid + captures: + 1: invalid.illegal.whitespace.markdown + 2: punctuation.definition.metadata.begin.markdown + set: + - meta_scope: meta.link.inline.markdown + - match: \) + scope: punctuation.definition.metadata.end.markdown + pop: true + - match: <(?=[^>)]*>) + scope: punctuation.definition.link.begin.markdown + push: + - match: \> + scope: punctuation.definition.link.end.markdown + set: link-title + - match: \s+ + scope: invalid.illegal.unexpected-whitespace.markdown + - match: (?=\S) + set: + - meta_scope: meta.link.inline.markdown + - match: '[^\s)]+' + scope: markup.underline.link.markdown + - match: \) + scope: punctuation.definition.metadata.end.markdown + pop: true + - match: (?!\n)\s+(?!\s*(?:[)('"]|$)) + scope: invalid.illegal.unexpected-whitespace.markdown + - match: (?=\s*(?!\))) + push: link-title + + link-inline-attr: + - match: '([ ]*)(\{)(?=[^}]*\})' + captures: + 1: invalid.illegal.whitespace.markdown + 2: punctuation.definition.attributes.begin.markdown + set: + - meta_scope: meta.link.inline.markdown + - include: tag-attributes + - include: immediately-pop + + link-inline-link-text: + - meta_content_scope: meta.link.inline.description.markdown + - include: link-text-allow-image + - match: \] + scope: meta.link.inline.markdown punctuation.definition.link.end.markdown + pop: true + + link-ref: + - match: |- + (?x: + (\[) + (?= {{balance_square_brackets}}? # balanced square brackets, backticks, taking into account escapes etc. + \] # Closing square bracket + [ ]? # Space + \[ # [ + [^\]]+ # anything other than ] + \] # ] + ) + ) + captures: + 1: meta.link.reference.markdown punctuation.definition.link.begin.markdown + push: [link-ref-attr, link-ref-after-text, link-ref-link-text] + - match: |- + (?x: + (\[)(?!\^) + (?= {{balance_square_brackets}}? # balanced square brackets, backticks, taking into account escapes etc. + \] + ) + ) + captures: + 1: meta.link.reference.markdown punctuation.definition.link.begin.markdown + push: link-ref-link-text + + link-ref-link-text: + - meta_content_scope: meta.link.reference.description.markdown + - include: link-text-allow-image + - match: \] + scope: meta.link.reference.markdown punctuation.definition.link.end.markdown + pop: true + + link-ref-after-text: + - match: '[ ]?(\[)([^\]]+)(\])' + captures: + 1: punctuation.definition.constant.begin.markdown + 2: constant.other.reference.link.markdown + 3: punctuation.definition.constant.end.markdown + scope: meta.link.reference.markdown + pop: true + + link-ref-attr: + - match: '([ ]*)(\{)(?=[^}]*\})' + captures: + 1: invalid.illegal.whitespace.markdown + 2: punctuation.definition.attributes.begin.markdown + set: + - meta_scope: meta.link.reference.markdown + - include: tag-attributes + - include: immediately-pop + + link-ref-literal: + - match: |- + (?x: + (\[) + (?= + {{balance_square_brackets}}? # balanced square brackets, backticks, taking into account escapes etc. + \] # Closing square bracket + [ ]? # Space + \[ # [ + \] # ] + ) + ) + captures: + 1: meta.link.reference.literal.markdown punctuation.definition.link.begin.markdown + push: [link-ref-literal-attr, link-ref-literal-after-text, link-ref-literal-link-text] + + link-ref-literal-link-text: + - meta_content_scope: meta.link.reference.literal.description.markdown + - include: link-text-allow-image + - match: \] + scope: meta.link.reference.literal.markdown punctuation.definition.link.end.markdown + pop: true + + link-ref-literal-after-text: + - match: '[ ]?(\[)(\])' + scope: meta.link.reference.literal.markdown + captures: + 1: punctuation.definition.constant.begin.markdown + 2: punctuation.definition.constant.end.markdown + pop: true + + link-ref-literal-attr: + - match: '([ ]*)(\{)(?=[^}]*\})' + captures: + 1: invalid.illegal.whitespace.markdown + 2: punctuation.definition.attributes.begin.markdown + set: + - meta_scope: meta.link.reference.literal.markdown + - include: tag-attributes + - include: immediately-pop + + link-ref-footnote: + - match: |- + (?x: + (\[\^) + ([^]]+) + (\]) + ) + captures: + 0: meta.link.reference.footnote.markdown-extra + 1: punctuation.definition.link.begin.markdown + 2: meta.link.reference.literal.footnote-id.markdown + 3: punctuation.definition.link.end.markdown + + link-ref-wiki: + - match: |- + (?x: + (\[\[) + (?= + {{balance_square_brackets}}? # balanced square brackets, backticks, taking into account escapes etc. + \]\] # Closing square bracket + ) + ) + captures: + 1: meta.link.reference.wiki.markdown punctuation.definition.link.begin.markdown + push: link-ref-wiki-link-text + + link-ref-wiki-link-text: + - meta_content_scope: meta.link.reference.wiki.description.markdown + - include: link-text-allow-image + - match: \]\] + scope: meta.link.reference.wiki.markdown punctuation.definition.link.end.markdown + pop: true + + reference-link-definition: + - match: |- + (?x: + [ ]{0,3} # Leading whitespace + (\[)(|(?:\\\]|[^]])+)(\])(:) # Reference name + [ \t]* # Optional whitespace + (?: + (<)([^>]*)(>) # The url + | (\S+) # The url + ) + ) + captures: + 1: punctuation.definition.constant.begin.markdown + 2: entity.name.reference.link.markdown + 3: punctuation.definition.constant.end.markdown + 4: punctuation.separator.key-value.markdown + 5: punctuation.definition.link.begin.markdown + 6: markup.underline.link.markdown + 7: punctuation.definition.link.end.markdown + 8: markup.underline.link.markdown + push: [link-ref-def-expect-end, link-title] + + list-paragraph: + - match: '^(?=(?:[ ]{4}|\t){2,}(?![>+*\s-]))(?={{indented_code_block}})' + push: + - include: indented-code-block + - match: $ + pop: true + - match: ^[ ]*{{block_quote}} + captures: + 1: punctuation.definition.blockquote.markdown + push: + - block-quote-meta + - block-quote-content + - include: fenced-code-blocks + - include: reference-link-definition + - match: \s+(?=\S) + push: + - match: ^\s*$ + pop: true + - match: ([ ]*)([*+-])((?:[ ](\[)([ xX])(\]))?\s) + captures: + 1: markup.list.unnumbered.markdown + 2: markup.list.unnumbered.bullet.markdown punctuation.definition.list_item.markdown + 3: markup.list.unnumbered.markdown + 4: markup.checkbox.begin.markdown-gfm punctuation.definition.checkbox.begin.markdown-gfm + 5: markup.checkbox.mark.markdown-gfm + 6: markup.checkbox.end.markdown-gfm punctuation.definition.checkbox.end.markdown-gfm + push: + - clear_scopes: 1 + - meta_content_scope: markup.list.unnumbered.markdown meta.paragraph.list.markdown + - include: list-content + - match: ([ ]*)(\d+([.)]))(?=\s) + captures: + 1: markup.list.numbered.markdown + 2: markup.list.numbered.bullet.markdown + 3: punctuation.definition.list_item.markdown + push: + - clear_scopes: 1 + - meta_content_scope: markup.list.numbered.markdown meta.paragraph.list.markdown + - include: list-content + - match: \s+ + scope: meta.paragraph.list.markdown + - match: (?=^{{atx_heading}}) + pop: true + - match: '(?=\S)' + push: list-content + - match: '(?=\S)' + pop: true + + list-content: + - meta_content_scope: meta.paragraph.list.markdown + - include: fenced-code-blocks + - match: ^ + pop: true + - include: thematic-break + - match: (?=\S)(?!{{list_item}}) + push: + - match: (?={{list_item}}) + pop: true + - include: inline-bold-italic-linebreak + - include: tag-kbd + - include: scope:text.html.basic + - match: $ + pop: true + + fenced-code-blocks: + - match: ^(?={{fenced_code_block_start}}) + push: fenced-code-block-content + + fenced-code-block-content: + - match: $ + pop: true + - include: fenced-syntaxes + - include: fenced-raw + + fenced-syntaxes: + - include: fenced-clojure + - include: fenced-c + - include: fenced-cpp + - include: fenced-csharp + - include: fenced-diff + - include: fenced-erlang + - include: fenced-graphviz + - include: fenced-golang + - include: fenced-haskell + - include: fenced-html-php + - include: fenced-html + - include: fenced-java + - include: fenced-javascript + - include: fenced-jsonc + - include: fenced-jspx + - include: fenced-jsx + - include: fenced-lisp + - include: fenced-lua + - include: fenced-matlab + - include: fenced-objc + - include: fenced-objcpp + - include: fenced-ocaml + - include: fenced-perl + - include: fenced-php + - include: fenced-python + - include: fenced-regexp + - include: fenced-rscript + - include: fenced-ruby + - include: fenced-rust + - include: fenced-scala + - include: fenced-shell-script + - include: fenced-sql + - include: fenced-tsx + - include: fenced-typescript + - include: fenced-xml + - include: fenced-yaml + # 3rd-party syntaxes + - include: fenced-ada + - include: fenced-akh + - include: fenced-coffee + - include: fenced-dart + - include: fenced-docker + - include: fenced-dosbatch + - include: fenced-elixir + - include: fenced-graphql + - include: fenced-ini + - include: fenced-jade + - include: fenced-julia + - include: fenced-kotlin + - include: fenced-less + - include: fenced-mermaid + - include: fenced-nim + - include: fenced-powershell + - include: fenced-reason + - include: fenced-sass + - include: fenced-scheme + - include: fenced-scss + - include: fenced-stata + - include: fenced-swift + - include: fenced-toml + + fenced-clojure: + - match: |- + (?x) + {{fenced_code_block_start}} + ((?i:clojure|clj)) + {{fenced_code_block_trailing_infostring_characters}} + captures: + 0: meta.code-fence.definition.begin.clojure.markdown-gfm + 2: punctuation.definition.raw.code-fence.begin.markdown + 5: constant.other.language-name.markdown + embed: scope:source.clojure + embed_scope: markup.raw.code-fence.clojure.markdown-gfm + escape: '{{code_fence_escape}}' + escape_captures: + 0: meta.code-fence.definition.end.clojure.markdown-gfm + 1: punctuation.definition.raw.code-fence.end.markdown + + fenced-c: + - match: |- + (?x) + {{fenced_code_block_start}} + ((?i:c)) + {{fenced_code_block_trailing_infostring_characters}} + captures: + 0: meta.code-fence.definition.begin.c.markdown-gfm + 2: punctuation.definition.raw.code-fence.begin.markdown + 5: constant.other.language-name.markdown + embed: scope:source.c + embed_scope: markup.raw.code-fence.c.markdown-gfm + escape: '{{code_fence_escape}}' + escape_captures: + 0: meta.code-fence.definition.end.c.markdown-gfm + 1: punctuation.definition.raw.code-fence.end.markdown + + fenced-cpp: + - match: |- + (?x) + {{fenced_code_block_start}} + ((?i:c\+\+|cpp)) + {{fenced_code_block_trailing_infostring_characters}} + captures: + 0: meta.code-fence.definition.begin.c++.markdown-gfm + 2: punctuation.definition.raw.code-fence.begin.markdown + 5: constant.other.language-name.markdown + embed: scope:source.c++ + embed_scope: markup.raw.code-fence.c++.markdown-gfm + escape: '{{code_fence_escape}}' + escape_captures: + 0: meta.code-fence.definition.end.c++.markdown-gfm + 1: punctuation.definition.raw.code-fence.end.markdown + + fenced-csharp: + - match: |- + (?x) + {{fenced_code_block_start}} + ((?i:csharp|c\#|cs)) + {{fenced_code_block_trailing_infostring_characters}} + captures: + 0: meta.code-fence.definition.begin.csharp.markdown-gfm + 2: punctuation.definition.raw.code-fence.begin.markdown + 5: constant.other.language-name.markdown + embed: scope:source.cs + embed_scope: markup.raw.code-fence.csharp.markdown-gfm + escape: '{{code_fence_escape}}' + escape_captures: + 0: meta.code-fence.definition.end.csharp.markdown-gfm + 1: punctuation.definition.raw.code-fence.end.markdown + + fenced-diff: + - match: |- + (?x) + {{fenced_code_block_start}} + ((?i:diff|patch)) + {{fenced_code_block_trailing_infostring_characters}} + captures: + 0: meta.code-fence.definition.begin.diff.markdown-gfm + 2: punctuation.definition.raw.code-fence.begin.markdown + 5: constant.other.language-name.markdown + embed: scope:source.diff + embed_scope: markup.raw.code-fence.diff.markdown-gfm + escape: '{{code_fence_escape}}' + escape_captures: + 0: meta.code-fence.definition.end.diff.markdown-gfm + 1: punctuation.definition.raw.code-fence.end.markdown + + fenced-erlang: + - match: |- + (?x) + {{fenced_code_block_start}} + ((?i:erlang|escript)) + {{fenced_code_block_trailing_infostring_characters}} + captures: + 0: meta.code-fence.definition.begin.erlang.markdown-gfm + 2: punctuation.definition.raw.code-fence.begin.markdown + 5: constant.other.language-name.markdown + embed: scope:source.erlang + embed_scope: markup.raw.code-fence.erlang.markdown-gfm + escape: '{{code_fence_escape}}' + escape_captures: + 0: meta.code-fence.definition.end.erlang.markdown-gfm + 1: punctuation.definition.raw.code-fence.end.markdown + + fenced-graphviz: + - match: |- + (?x) + {{fenced_code_block_start}} + ((?i:graphviz)) + {{fenced_code_block_trailing_infostring_characters}} + captures: + 0: meta.code-fence.definition.begin.graphviz.markdown-gfm + 2: punctuation.definition.raw.code-fence.begin.markdown + 5: constant.other.language-name.markdown + embed: scope:source.dot + embed_scope: markup.raw.code-fence.graphviz.markdown-gfm + escape: '{{code_fence_escape}}' + escape_captures: + 0: meta.code-fence.definition.end.graphviz.markdown-gfm + 1: punctuation.definition.raw.code-fence.end.markdown + + fenced-golang: + - match: |- + (?x) + {{fenced_code_block_start}} + ((?i:golang)) + {{fenced_code_block_trailing_infostring_characters}} + captures: + 0: meta.code-fence.definition.begin.go.markdown-gfm + 2: punctuation.definition.raw.code-fence.begin.markdown + 5: constant.other.language-name.markdown + embed: scope:source.go + embed_scope: markup.raw.code-fence.go.markdown-gfm + escape: '{{code_fence_escape}}' + escape_captures: + 0: meta.code-fence.definition.end.go.markdown-gfm + 1: punctuation.definition.raw.code-fence.end.markdown + + fenced-haskell: + - match: |- + (?x) + {{fenced_code_block_start}} + ((?i:haskell)) + {{fenced_code_block_trailing_infostring_characters}} + captures: + 0: meta.code-fence.definition.begin.haskell.markdown-gfm + 2: punctuation.definition.raw.code-fence.begin.markdown + 5: constant.other.language-name.markdown + embed: scope:source.haskell + embed_scope: markup.raw.code-fence.haskell.markdown-gfm + escape: '{{code_fence_escape}}' + escape_captures: + 0: meta.code-fence.definition.end.haskell.markdown-gfm + 1: punctuation.definition.raw.code-fence.end.markdown + + fenced-html-php: + - match: |- + (?x) + {{fenced_code_block_start}} + ((?i:html\+php)) + {{fenced_code_block_trailing_infostring_characters}} + captures: + 0: meta.code-fence.definition.begin.html-php.markdown-gfm + 2: punctuation.definition.raw.code-fence.begin.markdown + 5: constant.other.language-name.markdown + embed: scope:embedding.php + embed_scope: markup.raw.code-fence.html-php.markdown-gfm + escape: '{{code_fence_escape}}' + escape_captures: + 0: meta.code-fence.definition.end.html-php.markdown-gfm + 1: punctuation.definition.raw.code-fence.end.markdown + + fenced-html: + - match: |- + (?x) + {{fenced_code_block_start}} + ((?i:html)) + {{fenced_code_block_trailing_infostring_characters}} + captures: + 0: meta.code-fence.definition.begin.html.markdown-gfm + 2: punctuation.definition.raw.code-fence.begin.markdown + 5: constant.other.language-name.markdown + embed: scope:text.html.basic + embed_scope: markup.raw.code-fence.html.markdown-gfm + escape: '{{code_fence_escape}}' + escape_captures: + 0: meta.code-fence.definition.end.html.markdown-gfm + 1: punctuation.definition.raw.code-fence.end.markdown + + fenced-java: + - match: |- + (?x) + {{fenced_code_block_start}} + ((?i:java)) + {{fenced_code_block_trailing_infostring_characters}} + captures: + 0: meta.code-fence.definition.begin.java.markdown-gfm + 2: punctuation.definition.raw.code-fence.begin.markdown + 5: constant.other.language-name.markdown + embed: scope:source.java + embed_scope: markup.raw.code-fence.java.markdown-gfm + escape: '{{code_fence_escape}}' + escape_captures: + 0: meta.code-fence.definition.end.java.markdown-gfm + 1: punctuation.definition.raw.code-fence.end.markdown + + fenced-javascript: + - match: |- + (?x) + {{fenced_code_block_start}} + ((?i:javascript|js)) + {{fenced_code_block_trailing_infostring_characters}} + captures: + 0: meta.code-fence.definition.begin.javascript.markdown-gfm + 2: punctuation.definition.raw.code-fence.begin.markdown + 5: constant.other.language-name.markdown + embed: scope:source.js + embed_scope: markup.raw.code-fence.javascript.markdown-gfm + escape: '{{code_fence_escape}}' + escape_captures: + 0: meta.code-fence.definition.end.javascript.markdown-gfm + 1: punctuation.definition.raw.code-fence.end.markdown + + fenced-jsonc: + - match: |- + (?x) + {{fenced_code_block_start}} + ((?i:jsonc?)) + {{fenced_code_block_trailing_infostring_characters}} + captures: + 0: meta.code-fence.definition.begin.json.markdown-gfm + 2: punctuation.definition.raw.code-fence.begin.markdown + 5: constant.other.language-name.markdown + embed: scope:source.json + embed_scope: markup.raw.code-fence.json.markdown-gfm + escape: '{{code_fence_escape}}' + escape_captures: + 0: meta.code-fence.definition.end.json.markdown-gfm + 1: punctuation.definition.raw.code-fence.end.markdown + + fenced-jspx: + - match: |- + (?x) + {{fenced_code_block_start}} + ((?i:jspx?)) + {{fenced_code_block_trailing_infostring_characters}} + captures: + 0: meta.code-fence.definition.begin.jsp.markdown-gfm + 2: punctuation.definition.raw.code-fence.begin.markdown + 5: constant.other.language-name.markdown + embed: scope:text.html.jsp + embed_scope: markup.raw.code-fence.jsp.markdown-gfm + escape: '{{code_fence_escape}}' + escape_captures: + 0: meta.code-fence.definition.end.jsp.markdown-gfm + 1: punctuation.definition.raw.code-fence.end.markdown + + fenced-jsx: + - match: |- + (?x) + {{fenced_code_block_start}} + ((?i:jsx)) + {{fenced_code_block_trailing_infostring_characters}} + captures: + 0: meta.code-fence.definition.begin.jsx.markdown-gfm + 2: punctuation.definition.raw.code-fence.begin.markdown + 5: constant.other.language-name.markdown + embed: scope:source.jsx + embed_scope: markup.raw.code-fence.jsx.markdown-gfm + escape: '{{code_fence_escape}}' + escape_captures: + 0: meta.code-fence.definition.end.jsx.markdown-gfm + 1: punctuation.definition.raw.code-fence.end.markdown + + fenced-lisp: + - match: |- + (?x) + {{fenced_code_block_start}} + ((?i:lisp)) + {{fenced_code_block_trailing_infostring_characters}} + captures: + 0: meta.code-fence.definition.begin.lisp.markdown-gfm + 2: punctuation.definition.raw.code-fence.begin.markdown + 5: constant.other.language-name.markdown + embed: scope:source.lisp + embed_scope: markup.raw.code-fence.lisp.markdown-gfm + escape: '{{code_fence_escape}}' + escape_captures: + 0: meta.code-fence.definition.end.lisp.markdown-gfm + 1: punctuation.definition.raw.code-fence.end.markdown + + fenced-lua: + - match: |- + (?x) + {{fenced_code_block_start}} + ((?i:lua)) + {{fenced_code_block_trailing_infostring_characters}} + captures: + 0: meta.code-fence.definition.begin.lua.markdown-gfm + 2: punctuation.definition.raw.code-fence.begin.markdown + 5: constant.other.language-name.markdown + embed: scope:source.lua + embed_scope: markup.raw.code-fence.lua.markdown-gfm + escape: '{{code_fence_escape}}' + escape_captures: + 0: meta.code-fence.definition.end.lua.markdown-gfm + 1: punctuation.definition.raw.code-fence.end.markdown + + fenced-matlab: + - match: |- + (?x) + {{fenced_code_block_start}} + ((?i:matlab)) + {{fenced_code_block_trailing_infostring_characters}} + captures: + 0: meta.code-fence.definition.begin.matlab.markdown-gfm + 2: punctuation.definition.raw.code-fence.begin.markdown + 5: constant.other.language-name.markdown + embed: scope:source.matlab + embed_scope: markup.raw.code-fence.matlab.markdown-gfm + escape: '{{code_fence_escape}}' + escape_captures: + 0: meta.code-fence.definition.end.matlab.markdown-gfm + 1: punctuation.definition.raw.code-fence.end.markdown + + fenced-objc: + - match: |- + (?x) + {{fenced_code_block_start}} + ((?i:objc|obj-c|objectivec|objective-c)) + {{fenced_code_block_trailing_infostring_characters}} + captures: + 0: meta.code-fence.definition.begin.objc.markdown-gfm + 2: punctuation.definition.raw.code-fence.begin.markdown + 5: constant.other.language-name.markdown + embed: scope:source.objc + embed_scope: markup.raw.code-fence.objc.markdown-gfm + escape: '{{code_fence_escape}}' + escape_captures: + 0: meta.code-fence.definition.end.objc.markdown-gfm + 1: punctuation.definition.raw.code-fence.end.markdown + + fenced-objcpp: + - match: |- + (?x) + {{fenced_code_block_start}} + ((?i:objc\+\+|obj-c\+\+|objectivec\+\+|objective-c\+\+)) + {{fenced_code_block_trailing_infostring_characters}} + captures: + 0: meta.code-fence.definition.begin.objc++.markdown-gfm + 2: punctuation.definition.raw.code-fence.begin.markdown + 5: constant.other.language-name.markdown + embed: scope:source.objc++ + embed_scope: markup.raw.code-fence.objc++.markdown-gfm + escape: '{{code_fence_escape}}' + escape_captures: + 0: meta.code-fence.definition.end.objc++.markdown-gfm + 1: punctuation.definition.raw.code-fence.end.markdown + + fenced-ocaml: + - match: |- + (?x) + {{fenced_code_block_start}} + ((?i:ocaml)) + {{fenced_code_block_trailing_infostring_characters}} + captures: + 0: meta.code-fence.definition.begin.ocaml.markdown-gfm + 2: punctuation.definition.raw.code-fence.begin.markdown + 5: constant.other.language-name.markdown + embed: scope:source.ocaml + embed_scope: markup.raw.code-fence.ocaml.markdown-gfm + escape: '{{code_fence_escape}}' + escape_captures: + 0: meta.code-fence.definition.end.ocaml.markdown-gfm + 1: punctuation.definition.raw.code-fence.end.markdown + + fenced-perl: + - match: |- + (?x) + {{fenced_code_block_start}} + ((?i:perl)) + {{fenced_code_block_trailing_infostring_characters}} + captures: + 0: meta.code-fence.definition.begin.perl.markdown-gfm + 2: punctuation.definition.raw.code-fence.begin.markdown + 5: constant.other.language-name.markdown + embed: scope:source.perl + embed_scope: markup.raw.code-fence.perl.markdown-gfm + escape: '{{code_fence_escape}}' + escape_captures: + 0: meta.code-fence.definition.end.perl.markdown-gfm + 1: punctuation.definition.raw.code-fence.end.markdown + + fenced-php: + - match: |- + (?x) + {{fenced_code_block_start}} + ((?i:php|inc)) + {{fenced_code_block_trailing_infostring_characters}} + captures: + 0: meta.code-fence.definition.begin.php.markdown-gfm + 2: punctuation.definition.raw.code-fence.begin.markdown + 5: constant.other.language-name.markdown + embed: scope:source.php + embed_scope: markup.raw.code-fence.php.markdown-gfm + escape: '{{code_fence_escape}}' + escape_captures: + 0: meta.code-fence.definition.end.php.markdown-gfm + 1: punctuation.definition.raw.code-fence.end.markdown + + fenced-python: + - match: |- + (?x) + {{fenced_code_block_start}} + ((?i:python|py)) + {{fenced_code_block_trailing_infostring_characters}} + captures: + 0: meta.code-fence.definition.begin.python.markdown-gfm + 2: punctuation.definition.raw.code-fence.begin.markdown + 5: constant.other.language-name.markdown + embed: scope:source.python + embed_scope: markup.raw.code-fence.python.markdown-gfm + escape: '{{code_fence_escape}}' + escape_captures: + 0: meta.code-fence.definition.end.python.markdown-gfm + 1: punctuation.definition.raw.code-fence.end.markdown + + fenced-regexp: + - match: |- + (?x) + {{fenced_code_block_start}} + ((?i:regexp?)) + {{fenced_code_block_trailing_infostring_characters}} + captures: + 0: meta.code-fence.definition.begin.regexp.markdown-gfm + 2: punctuation.definition.raw.code-fence.begin.markdown + 5: constant.other.language-name.markdown + embed: scope:source.regexp + embed_scope: markup.raw.code-fence.regexp.markdown-gfm + escape: '{{code_fence_escape}}' + escape_captures: + 0: meta.code-fence.definition.end.regexp.markdown-gfm + 1: punctuation.definition.raw.code-fence.end.markdown + + fenced-rscript: + - match: |- + (?x) + {{fenced_code_block_start}} + ((?i:rscript|r|splus)) + {{fenced_code_block_trailing_infostring_characters}} + captures: + 0: meta.code-fence.definition.begin.r.markdown-gfm + 2: punctuation.definition.raw.code-fence.begin.markdown + 5: constant.other.language-name.markdown + embed: scope:source.r + embed_scope: markup.raw.code-fence.r.markdown-gfm + escape: '{{code_fence_escape}}' + escape_captures: + 0: meta.code-fence.definition.end.r.markdown-gfm + 1: punctuation.definition.raw.code-fence.end.markdown + + fenced-ruby: + - match: |- + (?x) + {{fenced_code_block_start}} + ((?i:ruby|rb|rbx)) + {{fenced_code_block_trailing_infostring_characters}} + captures: + 0: meta.code-fence.definition.begin.ruby.markdown-gfm + 2: punctuation.definition.raw.code-fence.begin.markdown + 5: constant.other.language-name.markdown + embed: scope:source.ruby + embed_scope: markup.raw.code-fence.ruby.markdown-gfm + escape: '{{code_fence_escape}}' + escape_captures: + 0: meta.code-fence.definition.end.ruby.markdown-gfm + 1: punctuation.definition.raw.code-fence.end.markdown + + fenced-rust: + - match: |- + (?x) + {{fenced_code_block_start}} + ((?i:rust|rs)) + {{fenced_code_block_trailing_infostring_characters}} + captures: + 0: meta.code-fence.definition.begin.rust.markdown-gfm + 2: punctuation.definition.raw.code-fence.begin.markdown + 5: constant.other.language-name.markdown + embed: scope:source.rust + embed_scope: markup.raw.code-fence.rust.markdown-gfm + escape: '{{code_fence_escape}}' + escape_captures: + 0: meta.code-fence.definition.end.rust.markdown-gfm + 1: punctuation.definition.raw.code-fence.end.markdown + + fenced-scala: + - match: |- + (?x) + {{fenced_code_block_start}} + ((?i:scala)) + {{fenced_code_block_trailing_infostring_characters}} + captures: + 0: meta.code-fence.definition.begin.scala.markdown-gfm + 2: punctuation.definition.raw.code-fence.begin.markdown + 5: constant.other.language-name.markdown + embed: scope:source.scala + embed_scope: markup.raw.code-fence.scala.markdown-gfm + escape: '{{code_fence_escape}}' + escape_captures: + 0: meta.code-fence.definition.end.scala.markdown-gfm + 1: punctuation.definition.raw.code-fence.end.markdown + + fenced-shell-script: + - match: |- + (?x) + {{fenced_code_block_start}} + ((?i:shell(?:-script)?|sh|bash|zsh)) + {{fenced_code_block_trailing_infostring_characters}} + captures: + 0: meta.code-fence.definition.begin.shell-script.markdown-gfm + 2: punctuation.definition.raw.code-fence.begin.markdown + 5: constant.other.language-name.markdown + embed: scope:source.shell.bash + embed_scope: markup.raw.code-fence.shell-script.markdown-gfm + escape: '{{code_fence_escape}}' + escape_captures: + 0: meta.code-fence.definition.end.shell-script.markdown-gfm + 1: punctuation.definition.raw.code-fence.end.markdown + + fenced-sql: + - match: |- + (?x) + {{fenced_code_block_start}} + ((?i:sql)) + {{fenced_code_block_trailing_infostring_characters}} + captures: + 0: meta.code-fence.definition.begin.sql.markdown-gfm + 2: punctuation.definition.raw.code-fence.begin.markdown + 5: constant.other.language-name.markdown + embed: scope:source.sql + embed_scope: markup.raw.code-fence.sql.markdown-gfm + escape: '{{code_fence_escape}}' + escape_captures: + 0: meta.code-fence.definition.end.sql.markdown-gfm + 1: punctuation.definition.raw.code-fence.end.markdown + + fenced-tsx: + - match: |- + (?x) + {{fenced_code_block_start}} + ((?i:tsx)) + {{fenced_code_block_trailing_infostring_characters}} + captures: + 0: meta.code-fence.definition.begin.tsx.markdown-gfm + 2: punctuation.definition.raw.code-fence.begin.markdown + 5: constant.other.language-name.markdown + embed: scope:source.tsx + embed_scope: markup.raw.code-fence.tsx.markdown-gfm + escape: '{{code_fence_escape}}' + escape_captures: + 0: meta.code-fence.definition.end.tsx.markdown-gfm + 1: punctuation.definition.raw.code-fence.end.markdown + + fenced-typescript: + - match: |- + (?x) + {{fenced_code_block_start}} + ((?i:typescript|ts)) + {{fenced_code_block_trailing_infostring_characters}} + captures: + 0: meta.code-fence.definition.begin.typescript.markdown-gfm + 2: punctuation.definition.raw.code-fence.begin.markdown + 5: constant.other.language-name.markdown + embed: scope:source.ts + embed_scope: markup.raw.code-fence.typescript.markdown-gfm + escape: '{{code_fence_escape}}' + escape_captures: + 0: meta.code-fence.definition.end.typescript.markdown-gfm + 1: punctuation.definition.raw.code-fence.end.markdown + + fenced-xml: + - match: |- + (?x) + {{fenced_code_block_start}} + ((?i:xml)) + {{fenced_code_block_trailing_infostring_characters}} + captures: + 0: meta.code-fence.definition.begin.xml.markdown-gfm + 2: punctuation.definition.raw.code-fence.begin.markdown + 5: constant.other.language-name.markdown + embed: scope:text.xml + embed_scope: markup.raw.code-fence.xml.markdown-gfm + escape: '{{code_fence_escape}}' + escape_captures: + 0: meta.code-fence.definition.end.xml.markdown-gfm + 1: punctuation.definition.raw.code-fence.end.markdown + + fenced-yaml: + - match: |- + (?x) + {{fenced_code_block_start}} + ((?i:yaml)) + {{fenced_code_block_trailing_infostring_characters}} + captures: + 0: meta.code-fence.definition.begin.yaml.markdown-gfm + 2: punctuation.definition.raw.code-fence.begin.markdown + 5: constant.other.language-name.markdown + embed: scope:source.yaml + embed_scope: markup.raw.code-fence.yaml.markdown-gfm + escape: '{{code_fence_escape}}' + escape_captures: + 0: meta.code-fence.definition.end.yaml.markdown-gfm + 1: punctuation.definition.raw.code-fence.end.markdown + + fenced-raw: + - match: |- + (?x) + {{fenced_code_block_start}} + {{fenced_code_block_language}}? + .*$\n? # all characters until EOL + captures: + 0: meta.code-fence.definition.begin.text.markdown-gfm + 2: punctuation.definition.raw.code-fence.begin.markdown + 5: constant.other.language-name.markdown + push: fenced-raw-content + + fenced-raw-content: + - meta_content_scope: markup.raw.code-fence.markdown-gfm + - match: '{{code_fence_escape}}' + captures: + 0: meta.code-fence.definition.end.text.markdown-gfm + 1: punctuation.definition.raw.code-fence.end.markdown + pop: true + + fenced-ada: + - match: |- + (?x) + {{fenced_code_block_start}} + ((?i:ada)) + {{fenced_code_block_trailing_infostring_characters}} + captures: + 0: meta.code-fence.definition.begin.ada.markdown-gfm + 2: punctuation.definition.raw.code-fence.begin.markdown + 5: constant.other.language-name.markdown + embed: scope:source.ada + embed_scope: markup.raw.code-fence.ada.markdown-gfm + escape: '{{code_fence_escape}}' + escape_captures: + 0: meta.code-fence.definition.end.ada.markdown-gfm + 1: punctuation.definition.raw.code-fence.end.markdown + + fenced-akh: + - match: |- + (?x) + {{fenced_code_block_start}} + ((?i:akh)) + {{fenced_code_block_trailing_infostring_characters}} + captures: + 0: meta.code-fence.definition.begin.akh.markdown-gfm + 2: punctuation.definition.raw.code-fence.begin.markdown + 5: constant.other.language-name.markdown + embed: scope:source.akh + embed_scope: markup.raw.code-fence.akh.markdown-gfm + escape: '{{code_fence_escape}}' + escape_captures: + 0: meta.code-fence.definition.end.akh.markdown-gfm + 1: punctuation.definition.raw.code-fence.end.markdown + + fenced-dosbatch: + - match: |- + (?x) + {{fenced_code_block_start}} + ((?i:bat|batch|cmd|dosbatch)) + {{fenced_code_block_trailing_infostring_characters}} + captures: + 0: meta.code-fence.definition.begin.dosbatch.markdown-gfm + 2: punctuation.definition.raw.code-fence.begin.markdown + 5: constant.other.language-name.markdown + embed: scope:source.dosbatch + embed_scope: markup.raw.code-fence.dosbatch.markdown-gfm + escape: '{{code_fence_escape}}' + escape_captures: + 0: meta.code-fence.definition.end.dosbatch.markdown-gfm + 1: punctuation.definition.raw.code-fence.end.markdown + + fenced-coffee: + - match: |- + (?x) + {{fenced_code_block_start}} + ((?i:coffee|cjsx)) + {{fenced_code_block_trailing_infostring_characters}} + captures: + 0: meta.code-fence.definition.begin.coffee.markdown-gfm + 2: punctuation.definition.raw.code-fence.begin.markdown + 5: constant.other.language-name.markdown + embed: scope:source.coffee + embed_scope: markup.raw.code-fence.coffee.markdown-gfm + escape: '{{code_fence_escape}}' + escape_captures: + 0: meta.code-fence.definition.end.coffee.markdown-gfm + 1: punctuation.definition.raw.code-fence.end.markdown + + fenced-dart: + - match: |- + (?x) + {{fenced_code_block_start}} + ((?i:dart)) + {{fenced_code_block_trailing_infostring_characters}} + captures: + 0: meta.code-fence.definition.begin.dart.markdown-gfm + 2: punctuation.definition.raw.code-fence.begin.markdown + 5: constant.other.language-name.markdown + embed: scope:source.dart + embed_scope: markup.raw.code-fence.dart.markdown-gfm + escape: '{{code_fence_escape}}' + escape_captures: + 0: meta.code-fence.definition.end.dart.markdown-gfm + 1: punctuation.definition.raw.code-fence.end.markdown + + fenced-docker: + - match: |- + (?x) + {{fenced_code_block_start}} + ((?i:docker)) + {{fenced_code_block_trailing_infostring_characters}} + captures: + 0: meta.code-fence.definition.begin.docker.markdown-gfm + 2: punctuation.definition.raw.code-fence.begin.markdown + 5: constant.other.language-name.markdown + embed: scope:source.shell.docker + embed_scope: markup.raw.code-fence.docker.markdown-gfm + escape: '{{code_fence_escape}}' + escape_captures: + 0: meta.code-fence.definition.end.docker.markdown-gfm + 1: punctuation.definition.raw.code-fence.end.markdown + + fenced-elixir: + - match: |- + (?x) + {{fenced_code_block_start}} + ((?i:elixir)) + {{fenced_code_block_trailing_infostring_characters}} + captures: + 0: meta.code-fence.definition.begin.elixir.markdown-gfm + 2: punctuation.definition.raw.code-fence.begin.markdown + 5: constant.other.language-name.markdown + embed: scope:source.elixir + embed_scope: markup.raw.code-fence.elixir.markdown-gfm + escape: '{{code_fence_escape}}' + escape_captures: + 0: meta.code-fence.definition.end.elixir.markdown-gfm + 1: punctuation.definition.raw.code-fence.end.markdown + + fenced-graphql: + - match: |- + (?x) + {{fenced_code_block_start}} + ((?i:graphql)) + {{fenced_code_block_trailing_infostring_characters}} + captures: + 0: meta.code-fence.definition.begin.graphql.markdown-gfm + 2: punctuation.definition.raw.code-fence.begin.markdown + 5: constant.other.language-name.markdown + embed: scope:source.graphql + embed_scope: markup.raw.code-fence.graphql.markdown-gfm + escape: '{{code_fence_escape}}' + escape_captures: + 0: meta.code-fence.definition.end.graphql.markdown-gfm + 1: punctuation.definition.raw.code-fence.end.markdown + + fenced-ini: + - match: |- + (?x) + {{fenced_code_block_start}} + ((?i:ini)) + {{fenced_code_block_trailing_infostring_characters}} + captures: + 0: meta.code-fence.definition.begin.ini.markdown-gfm + 2: punctuation.definition.raw.code-fence.begin.markdown + 5: constant.other.language-name.markdown + embed: scope:source.ini + embed_scope: markup.raw.code-fence.ini.markdown-gfm + escape: '{{code_fence_escape}}' + escape_captures: + 0: meta.code-fence.definition.end.ini.markdown-gfm + 1: punctuation.definition.raw.code-fence.end.markdown + + fenced-jade: + - match: |- + (?x) + {{fenced_code_block_start}} + ((?i:jade)) + {{fenced_code_block_trailing_infostring_characters}} + captures: + 0: meta.code-fence.definition.begin.jade.markdown-gfm + 2: punctuation.definition.raw.code-fence.begin.markdown + 5: constant.other.language-name.markdown + embed: scope:source.jade + embed_scope: markup.raw.code-fence.jade.markdown-gfm + escape: '{{code_fence_escape}}' + escape_captures: + 0: meta.code-fence.definition.end.jade.markdown-gfm + 1: punctuation.definition.raw.code-fence.end.markdown + + fenced-julia: + - match: |- + (?x) + {{fenced_code_block_start}} + ((?i:julia)) + {{fenced_code_block_trailing_infostring_characters}} + captures: + 0: meta.code-fence.definition.begin.julia.markdown-gfm + 2: punctuation.definition.raw.code-fence.begin.markdown + 5: constant.other.language-name.markdown + embed: scope:source.julia + embed_scope: markup.raw.code-fence.julia.markdown-gfm + escape: '{{code_fence_escape}}' + escape_captures: + 0: meta.code-fence.definition.end.julia.markdown-gfm + 1: punctuation.definition.raw.code-fence.end.markdown + + fenced-kotlin: + - match: |- + (?x) + {{fenced_code_block_start}} + ((?i:kotlin)) + {{fenced_code_block_trailing_infostring_characters}} + captures: + 0: meta.code-fence.definition.begin.kotlin.markdown-gfm + 2: punctuation.definition.raw.code-fence.begin.markdown + 5: constant.other.language-name.markdown + embed: scope:source.kotlin + embed_scope: markup.raw.code-fence.kotlin.markdown-gfm + escape: '{{code_fence_escape}}' + escape_captures: + 0: meta.code-fence.definition.end.kotlin.markdown-gfm + 1: punctuation.definition.raw.code-fence.end.markdown + + fenced-less: + - match: |- + (?x) + {{fenced_code_block_start}} + ((?i:less)) + {{fenced_code_block_trailing_infostring_characters}} + captures: + 0: meta.code-fence.definition.begin.less.markdown-gfm + 2: punctuation.definition.raw.code-fence.begin.markdown + 5: constant.other.language-name.markdown + embed: scope:source.less + embed_scope: markup.raw.code-fence.less.markdown-gfm + escape: '{{code_fence_escape}}' + escape_captures: + 0: meta.code-fence.definition.end.less.markdown-gfm + 1: punctuation.definition.raw.code-fence.end.markdown + + fenced-mermaid: + - match: |- + (?x) + {{fenced_code_block_start}} + ((?i:mermaid)) + {{fenced_code_block_trailing_infostring_characters}} + captures: + 0: meta.code-fence.definition.begin.mermaid.markdown-gfm + 2: punctuation.definition.raw.code-fence.begin.markdown + 5: constant.other.language-name.markdown + embed: scope:source.mermaid + embed_scope: + markup.raw.code-fence.mermaid.markdown-gfm + source.mermaid.embedded.markdown-gfm + escape: '{{code_fence_escape}}' + escape_captures: + 0: meta.code-fence.definition.end.mermaid.markdown-gfm + 1: punctuation.definition.raw.code-fence.end.markdown + + fenced-nim: + - match: |- + (?x) + {{fenced_code_block_start}} + ((?i:nim)) + {{fenced_code_block_trailing_infostring_characters}} + captures: + 0: meta.code-fence.definition.begin.nim.markdown-gfm + 2: punctuation.definition.raw.code-fence.begin.markdown + 5: constant.other.language-name.markdown + embed: scope:source.nim + embed_scope: markup.raw.code-fence.nim.markdown-gfm + escape: '{{code_fence_escape}}' + escape_captures: + 0: meta.code-fence.definition.end.nim.markdown-gfm + 1: punctuation.definition.raw.code-fence.end.markdown + + fenced-powershell: + - match: |- + (?x) + {{fenced_code_block_start}} + ((?i:pwsh|powershell)) + {{fenced_code_block_trailing_infostring_characters}} + captures: + 0: meta.code-fence.definition.begin.powershell.markdown-gfm + 2: punctuation.definition.raw.code-fence.begin.markdown + 5: constant.other.language-name.markdown + embed: scope:source.powershell + embed_scope: markup.raw.code-fence.powershell.markdown-gfm + escape: '{{code_fence_escape}}' + escape_captures: + 0: meta.code-fence.definition.end.powershell.markdown-gfm + 1: punctuation.definition.raw.code-fence.end.markdown + + fenced-reason: + - match: |- + (?x) + {{fenced_code_block_start}} + ((?i:re|reason)) + {{fenced_code_block_trailing_infostring_characters}} + captures: + 0: meta.code-fence.definition.begin.reason.markdown-gfm + 2: punctuation.definition.raw.code-fence.begin.markdown + 5: constant.other.language-name.markdown + embed: scope:source.reason + embed_scope: markup.raw.code-fence.reason.markdown-gfm + escape: '{{code_fence_escape}}' + escape_captures: + 0: meta.code-fence.definition.end.reason.markdown-gfm + 1: punctuation.definition.raw.code-fence.end.markdown + + fenced-sass: + - match: |- + (?x) + {{fenced_code_block_start}} + ((?i:sass)) + {{fenced_code_block_trailing_infostring_characters}} + captures: + 0: meta.code-fence.definition.begin.sass.markdown-gfm + 2: punctuation.definition.raw.code-fence.begin.markdown + 5: constant.other.language-name.markdown + embed: scope:source.sass + embed_scope: markup.raw.code-fence.sass.markdown-gfm + escape: '{{code_fence_escape}}' + escape_captures: + 0: meta.code-fence.definition.end.sass.markdown-gfm + 1: punctuation.definition.raw.code-fence.end.markdown + + fenced-scheme: + - match: |- + (?x) + {{fenced_code_block_start}} + ((?i:scheme)) + {{fenced_code_block_trailing_infostring_characters}} + captures: + 0: meta.code-fence.definition.begin.scheme.markdown-gfm + 2: punctuation.definition.raw.code-fence.begin.markdown + 5: constant.other.language-name.markdown + embed: scope:source.scheme + embed_scope: markup.raw.code-fence.scheme.markdown-gfm + escape: '{{code_fence_escape}}' + escape_captures: + 0: meta.code-fence.definition.end.scheme.markdown-gfm + 1: punctuation.definition.raw.code-fence.end.markdown + + fenced-scss: + - match: |- + (?x) + {{fenced_code_block_start}} + ((?i:scss)) + {{fenced_code_block_trailing_infostring_characters}} + captures: + 0: meta.code-fence.definition.begin.scss.markdown-gfm + 2: punctuation.definition.raw.code-fence.begin.markdown + 5: constant.other.language-name.markdown + embed: scope:source.scss + embed_scope: markup.raw.code-fence.scss.markdown-gfm + escape: '{{code_fence_escape}}' + escape_captures: + 0: meta.code-fence.definition.end.scss.markdown-gfm + 1: punctuation.definition.raw.code-fence.end.markdown + + fenced-stata: + - match: |- + (?x) + {{fenced_code_block_start}} + ((?i:s|stata|\{s\}|\{s[\s,].*\}|\{stata\}|\{stata[\s,].*\})) + {{fenced_code_block_trailing_infostring_characters}} + captures: + 0: meta.code-fence.definition.begin.stata.markdown-gfm + 2: punctuation.definition.raw.code-fence.begin.markdown + 5: constant.other.language-name.markdown + embed: scope:source.stata + embed_scope: markup.raw.code-fence.stata.markdown-gfm + escape: '{{code_fence_escape}}' + escape_captures: + 0: meta.code-fence.definition.end.stata.markdown-gfm + 1: punctuation.definition.raw.code-fence.end.markdown + + fenced-swift: + - match: |- + (?x) + {{fenced_code_block_start}} + ((?i:swift)) + {{fenced_code_block_trailing_infostring_characters}} + captures: + 0: meta.code-fence.definition.begin.swift.markdown-gfm + 2: punctuation.definition.raw.code-fence.begin.markdown + 5: constant.other.language-name.markdown + embed: scope:source.swift + embed_scope: markup.raw.code-fence.swift.markdown-gfm + escape: '{{code_fence_escape}}' + escape_captures: + 0: meta.code-fence.definition.end.swift.markdown-gfm + 1: punctuation.definition.raw.code-fence.end.markdown + + fenced-toml: + - match: |- + (?x) + {{fenced_code_block_start}} + ((?i:toml)) + {{fenced_code_block_trailing_infostring_characters}} + captures: + 0: meta.code-fence.definition.begin.toml.markdown-gfm + 2: punctuation.definition.raw.code-fence.begin.markdown + 5: constant.other.language-name.markdown + embed: scope:source.toml + embed_scope: markup.raw.code-fence.toml.markdown-gfm + escape: '{{code_fence_escape}}' + escape_captures: + 0: meta.code-fence.definition.end.toml.markdown-gfm + 1: punctuation.definition.raw.code-fence.end.markdown + + code-span: + - match: (`+)(?!`) + scope: punctuation.definition.raw.begin.markdown + push: + - meta_scope: markup.raw.inline.markdown + - match: \1(?!`) + scope: punctuation.definition.raw.end.markdown + pop: true + - match: '`+' + - match: ^\s*$\n? + scope: invalid.illegal.non-terminated.raw.markdown + pop: true + - include: paragraph-end + + thematic-break: + - match: (?={{thematic_break}}) + push: + - meta_scope: meta.separator.thematic-break.markdown + - match: '[-_*]+' + scope: punctuation.definition.thematic-break.markdown + - match: '$\n?' + pop: true + + disable-markdown: + - include: scope:text.html.basic + + disable-markdown-pop-at-tag: + - match: () + captures: + 1: meta.tag.block.any.html punctuation.definition.tag.begin.html + 2: meta.tag.block.any.html entity.name.tag.block.any.html + 3: meta.tag.block.any.html punctuation.definition.tag.end.html + pop: true + - include: disable-markdown + + disable-markdown-pop-after-tag: + - match: (?! + pop: true + - include: disable-markdown + + disable-markdown-pop-after-html-doctype: + - match: (?!))([^<]+)(()) + captures: + 1: markup.kbd.markdown meta.tag.inline.any.html + 2: punctuation.definition.tag.begin.html + 3: entity.name.tag.inline.any.html + 4: punctuation.definition.tag.end.html + 5: markup.kbd.content.markdown + 6: markup.kbd.markdown meta.tag.inline.any.html + 7: punctuation.definition.tag.begin.html + 8: entity.name.tag.inline.any.html + 9: punctuation.definition.tag.end.html + + link-text: + - match: \b__?(?=[^]_]+\]) # eat underscores where there is no pair before the end of the square brackets - it's not a formatting mark + - match: \b\*\*?(?=[^]*]+\]) # eat asterisks where there is no pair before the end of the square brackets - it's not a formatting mark + - include: escape + - include: ampersand + - include: code-span + - match: \[ # nested square brackets are allowed + push: + - include: link-text + - match: \] + pop: true + - include: bold + - include: italic + - include: hard-line-break + - include: tag-kbd + - include: scope:text.html.basic + + link-text-allow-image: + - include: link-text + - include: image-inline + - include: image-ref + + link-title: + - match: \' + scope: punctuation.definition.string.begin.markdown + set: + - meta_scope: string.other.link.description.title.markdown + - match: \' + scope: punctuation.definition.string.end.markdown + pop: true + - include: non-terminated-link-title + - match: \" + scope: punctuation.definition.string.begin.markdown + set: + - meta_scope: string.other.link.description.title.markdown + - match: \" + scope: punctuation.definition.string.end.markdown + pop: true + - include: non-terminated-link-title + - match: \( + scope: punctuation.definition.string.begin.markdown + set: + - meta_scope: string.other.link.description.title.markdown + - match: \) + scope: punctuation.definition.string.end.markdown + pop: true + - include: non-terminated-link-title + - match: $|(?=\S) + pop: true + + non-terminated-link-title: + - match: ^\s*$\n? + scope: invalid.illegal.non-terminated.link-title.markdown + pop: true + + link-ref-def-expect-end: + - meta_scope: meta.link.reference.def.markdown + - match: $ + pop: true + - match: \s*\S+ + scope: invalid.illegal.expected-eol.markdown + +###[ LINK/IMAGE/REFERENCE ATTRIBUTES ]######################################## + + tag-attributes: + # https://kramdown.gettalong.org/syntax.html#span-ials + # https://michelf.ca/projects/php-markdown/extra/ + # https://pandoc.org/MANUAL.html#extension-link_attributes + - match: \} + scope: punctuation.definition.attributes.end.markdown + pop: true + - match: \, + scope: punctuation.separator.mapping.pair.markdown + - match: '{{tag_attribute_name_start}}' + push: [tag-attr-meta, tag-attr-equals, tag-attr-name] + + tag-attr-name: + - meta_scope: entity.other.attribute-name.markdown + - match: '{{tag_attribute_name_break}}' + pop: true + - match: '["''`<]' + scope: invalid.illegal.attribute-name.markdown + + tag-attr-meta: + - meta_scope: meta.attribute-with-value.markdown + - include: immediately-pop + + tag-attr-equals: + - match: = + scope: punctuation.separator.key-value.markdown + set: tag-attr-value + - include: else-pop + + tag-attr-value: + - match: \" + scope: punctuation.definition.string.begin.markdown + set: + - meta_scope: string.quoted.double.markdown + - match: \" + scope: punctuation.definition.string.end.markdown + pop: true + - match: \' + scope: punctuation.definition.string.begin.markdown + set: + - meta_scope: string.quoted.single.markdown + - match: \' + scope: punctuation.definition.string.end.markdown + pop: true + - match: '{{tag_unquoted_attribute_start}}' + set: + - meta_scope: string.unquoted.markdown + - match: '{{tag_unquoted_attribute_break}}' + pop: true + - match: '["''`<]' + scope: invalid.illegal.attribute-value.markdown + - include: else-pop + +###[ TABLE ]################################################################## + + table: + - match: ^(?={{table_first_row}}) + push: + - meta_content_scope: meta.table.header.markdown-gfm + - match: \| + scope: punctuation.separator.table-cell.markdown + - include: inline-bold-italic + - match: $\n? + set: + - match: ^ + set: + - meta_content_scope: meta.table.header-separator.markdown-gfm + - match: \| + scope: punctuation.separator.table-cell.markdown + - match: ':' + scope: punctuation.definition.table-cell-alignment.markdown + - match: -+ + scope: punctuation.section.table-header.markdown + - match: $\n? + set: + - meta_content_scope: meta.table.markdown-gfm + - match: |- # The table is broken at the first empty line, or beginning of another block-level structure + (?x)^ + (?= {{block_quote}} + | {{indented_code_block}}(?!$) + | {{atx_heading}} + | {{thematic_break}} + | \s*$ + ) + pop: true + - match: \| + scope: punctuation.separator.table-cell.markdown + - match: (?={{balanced_emphasis}}) + push: + - include: bold + - include: italic + - include: immediately-pop + - match: |- + (?x) + (?!{{backticks}}) + `+ + scope: invalid.deprecated.unescaped-backticks.markdown + - include: inline + - include: tag-kbd + - include: scope:text.html.basic + +###[ CRITIC MARKUP ]########################################################## + + critic-inline: + # inline critic markup + # http://criticmarkup.com/spec.php + - include: critic-inline-additions + - include: critic-inline-comments + - include: critic-inline-deletions + - include: critic-inline-highlights + - include: critic-inline-substitutions + + critic-inline-additions: + - match: \{\+\+ + scope: punctuation.definition.critic.begin.markdown + push: critic-inline-addition-content + + critic-inline-addition-content: + - meta_scope: markup.critic.addition.markdown + - meta_content_scope: markup.inserted.critic.markdown + - match: \+\+\} + scope: punctuation.definition.critic.end.markdown + pop: true + - include: critic-inline-common + + critic-inline-comments: + - match: '{>>' + scope: punctuation.definition.critic.begin.markdown + push: critic-inline-comment-content + + critic-inline-comment-content: + - meta_scope: markup.critic.comment.markdown + - meta_content_scope: comment.critic.markdown + - match: '<<}' + scope: punctuation.definition.critic.end.markdown + pop: true + - include: critic-inline-common + + critic-inline-deletions: + - match: '{--' + scope: punctuation.definition.critic.begin.markdown + push: critic-inline-deletion-content + + critic-inline-deletion-content: + - meta_scope: markup.critic.deletion.markdown + - meta_content_scope: markup.deleted.critic.markdown + - match: '--}' + scope: punctuation.definition.critic.end.markdown + pop: true + - include: critic-inline-common + + critic-inline-highlights: + - match: '{==' + scope: punctuation.definition.critic.begin.markdown + push: critic-inline-highlight-content + + critic-inline-highlight-content: + - meta_scope: markup.critic.highlight.markdown + - meta_content_scope: markup.info.critic.markdown + - match: '==}' + scope: punctuation.definition.critic.end.markdown + pop: true + - include: critic-inline-common + + critic-inline-substitutions: + - match: '{~~' + scope: punctuation.definition.critic.begin.markdown + push: critic-inline-substitution-deleted + + critic-inline-substitution-deleted: + - meta_scope: markup.critic.substitution.markdown + - meta_content_scope: markup.deleted.critic.markdown + - match: (?=~>) + set: + - meta_include_prototype: false + - match: '~>' + scope: punctuation.separator.critic.markdown + set: critic-inline-substitution-inserted + - include: critic-inline-substitution-inserted + + critic-inline-substitution-inserted: + - meta_scope: markup.critic.substitution.markdown + - meta_content_scope: markup.inserted.critic.markdown + - match: '~~}' + scope: punctuation.definition.critic.end.markdown + pop: true + - include: critic-inline-common + + critic-inline-common: + - match: ^(?=\s*$) + pop: true + - include: inline-bold-italic + +###[ PROTOTYPES ]############################################################# + + else-pop: + - match: (?=\S) + pop: true + + immediately-pop: + - match: '' + pop: true diff --git a/syntaxes/MultiMarkdown.sublime-settings b/syntaxes/MultiMarkdown.sublime-settings new file mode 100644 index 00000000..29c7779c --- /dev/null +++ b/syntaxes/MultiMarkdown.sublime-settings @@ -0,0 +1,3 @@ +{ + "trim_trailing_white_space_on_save": false +} diff --git a/syntaxes/MultiMarkdown.sublime-syntax b/syntaxes/MultiMarkdown.sublime-syntax new file mode 100644 index 00000000..5bf6f59f --- /dev/null +++ b/syntaxes/MultiMarkdown.sublime-syntax @@ -0,0 +1,35 @@ +%YAML 1.2 +--- +name: MultiMarkdown +scope: text.html.markdown.multimarkdown + +first_line_match: (?i:^format:\s*complete\s*$) + +variables: + header: ([A-Za-z0-9][\w -]*)(:) + +contexts: + main: + - match: ^(?={{header}}) + push: multimarkdown-header + - match: ^ + set: multimarkdown-content + + multimarkdown-header: + - match: ^$ + pop: true + - match: ^(?:{{header}}\s*)? + captures: + 1: keyword.other.multimarkdown + 2: punctuation.separator.key-value.multimarkdown + push: multimarkdown-header-value + + multimarkdown-header-value: + - meta_scope: meta.header.multimarkdown + - meta_content_scope: string.unquoted.multimarkdown + - match: \n + pop: true + + multimarkdown-content: + - meta_scope: meta.content.multimarkdown + - include: scope:text.html.markdown diff --git a/Symbol List - Heading.tmPreferences b/syntaxes/Symbol List - Heading.tmPreferences similarity index 69% rename from Symbol List - Heading.tmPreferences rename to syntaxes/Symbol List - Heading.tmPreferences index da10a9ff..aa5e6a29 100644 --- a/Symbol List - Heading.tmPreferences +++ b/syntaxes/Symbol List - Heading.tmPreferences @@ -2,8 +2,6 @@ - name - Symbol List: Heading scope text.html.markdown markup.heading settings @@ -17,11 +15,11 @@ s/\[([^]]+)\]/$1/g; s/\s*#+\s*$//g; s/^\s*#(#*)\s*/$1/g; - s/^#{5}/ /g; - s/^#{4}/ /g; - s/^#{3}/ /g; - s/^#{2}/ /g; - s/^#{1}/ /g; + s/^#{5}/ /g; + s/^#{4}/ /g; + s/^#{3}/ /g; + s/^#{2}/ /g; + s/^#{1}/ /g; s/^(-+)\s*$/ $1/ showInIndexedSymbolList @@ -31,7 +29,5 @@ s/\s*#+\s*$//g; - uuid - C02A37C1-E770-472F-A13E-358FF0C6AD89 diff --git a/Symbol List - Hide.tmPreferences b/syntaxes/Symbol List - Hide.tmPreferences similarity index 79% rename from Symbol List - Hide.tmPreferences rename to syntaxes/Symbol List - Hide.tmPreferences index 7fb672a7..08321d7b 100644 --- a/Symbol List - Hide.tmPreferences +++ b/syntaxes/Symbol List - Hide.tmPreferences @@ -2,8 +2,6 @@ - name - Symbol List: Hide scope text.html.markdown markup.raw.block.fenced.markdown, text.html.markdown meta.toc-list.id settings @@ -13,7 +11,5 @@ showInIndexedSymbolList 0 - uuid - 626899F0-53C2-11E3-8F96-0800200C9A66 diff --git a/syntaxes/Symbol List - Reference Link.tmPreferences b/syntaxes/Symbol List - Reference Link.tmPreferences new file mode 100644 index 00000000..5e04b0b9 --- /dev/null +++ b/syntaxes/Symbol List - Reference Link.tmPreferences @@ -0,0 +1,16 @@ + + + + scope + text.html.markdown meta.link.reference.def + settings + + showInSymbolList + 1 + symbolTransformation + + + + diff --git a/tests/GFM.md b/tests/GFM.md deleted file mode 100644 index b5ae217d..00000000 --- a/tests/GFM.md +++ /dev/null @@ -1,158 +0,0 @@ -# Strikethrough - -~~This text should be parsed as _strikethroughed_.~~ - -~~There may be __bold__ or _italic_ text inside strikethroughed text.~~ - -~~There may be a keyboard shortcut like Enter inside strikethroughed text.~~ - -__There may be ~~strikethroughed text~~ inside bold text.__ -_There may be ~~strikethroughed text~~ inside italic text._ - -~~ If there is a space in the beginning or end, it won't work as per the [GFM][GFM] docs ~~ - -~~Strikethrough can be applied to -multiple lines. Just keep in mind -not to put any space in the beginning or end.~~ - -# Underscore In Words - -The word `complicated` must be neither bold nor italic below: - -perform_complicated_task -perform__complicated__task - -But the first part below is italic and bold respectively: - -_perform_complicated_task -__perform__complicated__task - -# Keyboard Shortcuts - -Keyboard shortcuts below should be highlighted: - ---- - -A keyboard shortcut Enter can be in paragraph. - -* A keyboard shortcut Enter can be in list. - -_A keyboard shortcut Enter can be in italic._ -__A keyboard shortcut Enter can be in bold.__ - -~~A keyboard shortcut Enter can be in deleted text.~~ - -

A keyboard shortcut Enter can be in HTML.

- -
- A keyboard shortcut Enter can be in block level tags. -
- -# Fenced Code Blocks - -## In / Near List Items - -Below fenced code blocks _should_ be highlighted. - ---- - -* List item - - ```js - for (var i = 0; i < 10; i++) { - console.log(i); - } - ``` - -* List item - -```js -for (var i = 0; i < 10; i++) { - console.log(i); -} -``` - ---- - -Below are _not_ recommended by the [GFM docs][GFM] due to the lack of preceding blank line; but still supported and highlighted by the GFM. So, they _should_ be highlighted. - ---- - -* List item - ```js - for (var i = 0; i < 10; i++) { - console.log(i); - } - ``` - -* List item -```js -for (var i = 0; i < 10; i++) { - console.log(i); -} -``` - -## In / Near Paragraphs - -Below is _not_ a _fenced_ code block, just a normal code block. - ---- - -Paragraph - - ```js - for (var i = 0; i < 10; i++) { - console.log(i); - } - ``` - ---- - -Below 2 blocks are fenced code blocks. They _should_ be highlighted. - ---- - -Paragraph - -```js -for (var i = 0; i < 10; i++) { - console.log(i); -} -``` - -Paragraph -```js -for (var i = 0; i < 10; i++) { - console.log(i); -} -``` - ---- - -Below is not any type of code block. It _should not_ be highlighted. - ---- - -Paragraph - ```js - for (var i = 0; i < 10; i++) { - console.log(i); - } - ``` - -# Links - -[I'm an inline link](http://fakewebsite.com/fakepage) -![I'm an inline image](http://fakewebsite.com/fakeimg.png) -[I'm a link][testLink] -![I'm an image][imageLink] -[I'm a link literal][] -[I'm a link literal too] -[i'm a CASE INSENSITIVE link] - -[GFM]: https://help.github.com/articles/github-flavored-markdown -[testLink]: http://fakewebsite.com/fakepage -[imageLink]: http://fakewebsite.com/fakeimg.png -[I'm a link literal]: http://fakewebsite.com/fakepage -[I'm a link literal too]: http://fakewebsite.com/fakepage -[I'M A case insensitive LINK]: http://fakewebsite.com/fakepage diff --git a/tests/Markdown.md b/tests/Markdown.md deleted file mode 100644 index 85ede670..00000000 --- a/tests/Markdown.md +++ /dev/null @@ -1,122 +0,0 @@ -Source: https://github.com/textmate/markdown.tmbundle/blob/master/Tests/test-minimal.markdown - -Inline styles -=============== - -_italic_ - -_italic one_ not italic _italic two_ - -_italic\__ - -_italic \__ - -stuff * not italic* - -*italic__* - -_all _ italic_ - -_italic -end italic_ - -\\\\_italic\\_ - -\\\\_italic\\\_\\\\_ - -\\\\_italic\\_ - -\_ not italic _ - -_not italic _ - -\\\\_not italic\_ - -_not italic \_ - -\\\_not italic\\_ - -_not italic - -not end italic_ - -__bold__ - -**bold\*** - -___bold_and_italic___ - -***bold_and_italic*** - -`raw more` - -``dobule ` raw`` - -`raw \` more` - -Headings -================ - -heading 2 ----------- - -## heading 2 - -### heading 3 - -###### heading 6 - -Horizontal lines -================= - -*** - -* * * - -___ - -__ __ __ - -- - - - ----------------- - ----- - - -Block formatting -================ - -Lists ----------------- - - * This *is a list!* - * This is another list item. - But this one spans *two* lines. - * Another list item with __inline__ formatting - * This one is tricky - * *This is a list* - - Because this should still be a list item. - -1. This is a list item too -2. This list is numbered - -1986\. This shouldn't be a list. - -Code block ---------------- - - asdfsdafasdf - This is code. - Isn't it pretty! - -Quotes ---------------- - -> Here is a quote block -This quote continues on. Line breaking is OK in markdown -> Here it is again -> Lah-di-dah -> I should really match headings in here too: -> ## This is a heading in a block quote diff --git a/tests/__init__.py b/tests/__init__.py new file mode 100644 index 00000000..28fbd518 --- /dev/null +++ b/tests/__init__.py @@ -0,0 +1,117 @@ +import sublime + +from textwrap import dedent +from unittesting import DeferrableTestCase + + +class DereferrablePanelTestCase(DeferrableTestCase): + + @classmethod + def setUpClass(cls): + """ + Set up global test environment once for all tests owned by this class. + """ + cls.window = sublime.active_window() + cls.view = cls.window.create_output_panel("MarkdownUnitTests", unlisted=True) + settings = cls.view.settings() + settings.set("auto_indent", False) + settings.set("detect_indentation", False) + settings.set("fold_buttons", False) + settings.set("gutter", False) + settings.set("line_numbers", False) + settings.set("scroll_past_end", False) + settings.set("syntax", "Packages/MarkdownEditing/syntaxes/Markdown.sublime-syntax") + settings.set("word_wrap", False) + cls.view = cls.window.create_output_panel("MarkdownUnitTests", unlisted=True) + + @classmethod + def tearDownClass(cls): + """ + Teardown global test environment once all tests finished. + """ + cls.window.destroy_output_panel("MarkdownUnitTests") + + @classmethod + def addCaretAt(cls, row, col): + """ + Add caret to given point (row, col) + + :param row: The natural 1-based row number. 1=first row + :param col: The natural 1-based column number. 1=first column + """ + cls.view.sel().add(cls.textPoint(row, col)) + + @classmethod + def setCaretTo(cls, row, col): + """ + Move caret to given point (row, col) + + :param row: The natural 1-based row number. 1=first row + :param col: The natural 1-based column number. 1=first column + """ + cls.view.sel().clear() + cls.view.sel().add(cls.textPoint(row, col)) + + @classmethod + def setBlockText(cls, text): + """ + Replace everything with given block text + + :param text: The triple quoted block text to put into scratch view. + """ + cls.setText(dedent(text).strip("\n")) + + @classmethod + def setText(cls, text): + """ + Replace everything with given text + + :param text: The text to put into scratch view. + """ + cls.view.run_command("select_all") + cls.view.run_command("right_delete") + cls.view.run_command("insert", {"characters": text}) + + @classmethod + def getText(cls): + """ + Return view's text content + """ + return cls.view.substr(sublime.Region(0, cls.view.size())) + + @classmethod + def getRow(cls, row): + """ + Return row's text content. + + :param row: The natural 1-based row number. 1=first row + """ + return cls.view.substr(cls.view.line(cls.textPoint(row, 0))) + + @classmethod + def textPoint(cls, row, col): + """ + Return textpoint for given row,col coordinats. + + :param row: The natural 1-based row number. 1=first row + :param col: The natural 1-based column number. 1=first column + """ + return cls.view.text_point(row - 1, col - 1) + + def assertEqualBlockText(self, text): + """ + Assert view containing `text` after detenting and stripping whitespace. + + :param text: + Triple quoted text, which is detented and stripped + before being compared with view's content. + """ + self.assertEqual(self.getText(), dedent(text).strip("\n")) + + def assertEqualText(self, text): + """ + Assert view containing `text`. + + :param text: The text expected to be equal with view's content. + """ + self.assertEqual(self.getText(), text) diff --git a/tests/requirements.txt b/tests/requirements.txt new file mode 100644 index 00000000..90f454f2 --- /dev/null +++ b/tests/requirements.txt @@ -0,0 +1,9 @@ +mccabe == 0.6.1 ; python_version == '3.3' +pycodestyle == 2.3.1 ; python_version == '3.3' +pyflakes == 1.6.0 ; python_version == '3.3' +flake8 == 3.5.0 ; python_version == '3.3' +mccabe == 0.6.1 ; python_version == '3.8' +pycodestyle == 2.7.0 ; python_version == '3.8' +pyflakes == 2.3.1 ; python_version == '3.8' +flake8 == 3.9.2 ; python_version == '3.8' +black == 21.5b1 ; python_version == '3.8' diff --git a/tests/syntax_test_GFM.md b/tests/syntax_test_GFM.md deleted file mode 100644 index 5676530c..00000000 --- a/tests/syntax_test_GFM.md +++ /dev/null @@ -1,457 +0,0 @@ - - -Inline styles -============= - -_italic_ - - - - - -_italic one_ not italic _italic two_ - - - - - - - - -_italic\__ - - - -_italic \__ - - - -stuff * not italic* - - - - -*italic__* - - -_all _ italic_ - - - - -_italic -end italic_ - - -\\\\_italic\\_ - - -\\\\_italic\\\_\\\\_ - - -\\\\_italic\\_ - - -\_ not italic _ - - -_not italic _ - - -\\\\_not italic\_ - - -_not italic \_ - - -\\\_not italic\\_ - - -_not italic - - -not end italic_ - - -__bold__ - - - - -**bold\*** - - - - - - -___bold_and_italic___ - - -***bold_and_italic*** - - -`raw more` - - - - -``dobule ` raw`` - - - - -Headings -================ - - - -heading 2 ----------- - - - -## heading 2 - - - -### heading 3 - - - -###### heading 6 - - - -Horizontal lines -================= - -*** - - - - -* * * - - - - -___ - - - - -__ __ __ - - - - - -- - - - - - - - ----------------- - - - - - -Block formatting -================ - -Lists ----------------- - - * This *is a list!* - - - - - - * This is another list item. - But this one spans *two* lines. - - - - - * Another list item with __inline__ formatting - - - - - - * This one is tricky - - - - * *This is a list* - - - - - Because this should still be a list item. - - - -1. This is a list item too - - -2. This list is numbered - - - -1986\. This shouldn't be a list. - - -Code block ---------------- - - asdfsdafasdf - This is code. - Isn't it pretty! - -Quotes ---------------- - -> Here is a quote block - - -This quote continues on. Line breaking is OK in markdown - -> Here it is again -> Lah-di-dah -> I should really match headings in here too: -> ## This is a heading in a block quote - - - -# Strikethrough - -~~This text should be parsed as _strikethroughed_.~~ - - - - -~~There may be __bold__ or _italic_ text inside strikethroughed text.~~ - - - - - -~~There may be a keyboard shortcut like Enter inside strikethroughed text.~~ - - - - -__There may be ~~strikethroughed text~~ inside bold text.__ - - - -_There may be ~~strikethroughed text~~ inside italic text._ - - - -~~ If there is a space in the beginning or end, it won't work as per the [GFM][GFM] docs ~~ - - -~~Strikethrough can be applied to -multiple lines. Just keep in mind -not to put any space in the beginning or end.~~ - - -# Underscore In Words - -The word `complicated` must be neither bold nor italic below: - -perform_complicated_task - -perform__complicated__task - - -But the first part below is italic and bold respectively: - -_perform_complicated_task - -__perform__complicated__task - - -# Keyboard Shortcuts - -Keyboard shortcuts below should be highlighted: - ---- - -A keyboard shortcut Enter can be in paragraph. - - - - - - - - -* A keyboard shortcut Enter can be in list. - - - - - - - - - -_A keyboard shortcut Enter can be in italic._ - - - - - - - - - -__A keyboard shortcut Enter can be in bold.__ - - - - - - - - - -~~A keyboard shortcut Enter can be in deleted text.~~ - - - - - - - - - -

A keyboard shortcut Enter can be in HTML.

- - - - - - - - - -
- A keyboard shortcut Enter can be in block level tags. - - - - - - - - -
- -# Fenced Code Blocks - -## In / Near List Items - -Below fenced code blocks _should_ be highlighted. - ---- - -* List item - - ```js - for (var i = 0; i < 10; i++) { - console.log(i); - } - ``` - - -* List item - -```js -for (var i = 0; i < 10; i++) { - console.log(i); -} -``` - ---- - -Below are _not_ valid fenced code blocks according to the [GFM docs][GFM]. It says there must be a blank line before the code block. However, GitHub highlights them. So, they _should_ be highlighted. - - ---- - - - List item - ```js - for (var i = 0; i < 10; i++) { - console.log(i); - } - ``` - - - - List item - ```js - for (var i = 0; i < 10; i++) { - console.log(i); - } - ``` - - -## In / Near Paragraphs - -Below is _not_ a _fenced_ code block, just a normal code block. - ---- - -Paragraph - - ```js - for (var i = 0; i < 10; i++) { - console.log(i); - } - ``` - ---- - -Below 2 blocks are fenced code blocks. They _should_ be highlighted. - ---- - -Paragraph - -```js -for (var i = 0; i < 10; i++) { - console.log(i); -} -``` - - -Paragraph -```js -for (var i = 0; i < 10; i++) { - console.log(i); -} -``` - - ---- - -Below is not any type of code block. It _should not_ be highlighted. - ---- - -Paragraph - ```js - for (var i = 0; i < 10; i++) { - console.log(i); - } - ``` - - -[GFM]: https://help.github.com/articles/github-flavored-markdown diff --git a/tests/syntax_test_Markdown.md b/tests/syntax_test_Markdown.md deleted file mode 100644 index 0c80f6c7..00000000 --- a/tests/syntax_test_Markdown.md +++ /dev/null @@ -1,229 +0,0 @@ - - -Inline styles -============= - -_italic_ - - - - - -_italic one_ not italic _italic two_ - - - - - - - - -_italic\__ - - - -_italic \__ - - - -stuff * not italic* - - - - -*italic__* - - -_all _ italic_ - - - - -_italic -end italic_ - - -\\\\_italic\\_ - - -\\\\_italic\\\_\\\\_ - - -\\\\_italic\\_ - - -\_ not italic _ - - -_not italic _ - - -\\\\_not italic\_ - - -_not italic \_ - - -\\\_not italic\\_ - - -_not italic - - -not end italic_ - - -__bold__ - - - - -**bold\*** - - - - - - -___bold_and_italic___ - - -***bold_and_italic*** - - -`raw more` - - - - -``dobule ` raw`` - - - - -Headings -================ - - - -heading 2 ----------- - - - -## heading 2 - - - -### heading 3 - - - -###### heading 6 - - - -Horizontal lines -================= - -*** - - - - -* * * - - - - -___ - - - - -__ __ __ - - - - - -- - - - - - - - ----------------- - - - - - -Block formatting -================ - -Lists ----------------- - - * This *is a list!* - - - - - - * This is another list item. - But this one spans *two* lines. - - - - - * Another list item with __inline__ formatting - - - - - - * This one is tricky - - - - * *This is a list* - - - - - Because this should still be a list item. - - - -1. This is a list item too - - -2. This list is numbered - - - -1986\. This shouldn't be a list. - - -Code block ---------------- - - asdfsdafasdf - This is code. - Isn't it pretty! - -Quotes ---------------- - -> Here is a quote block - - -This quote continues on. Line breaking is OK in markdown - -> Here it is again -> Lah-di-dah -> I should really match headings in here too: -> ## This is a heading in a block quote - - diff --git a/tests/syntax_test_markdown.md b/tests/syntax_test_markdown.md new file mode 100644 index 00000000..642cf8c6 --- /dev/null +++ b/tests/syntax_test_markdown.md @@ -0,0 +1,2848 @@ +| SYNTAX TEST "Packages/MarkdownEditing/syntaxes/Markdown.sublime-syntax" + +# Heading +| <- markup.heading.1 punctuation.definition.heading +|^^^^^^^^^ markup.heading.1.markdown +|^ - entity.name.section +| ^^^^^^ entity.name.section +| ^ meta.whitespace.newline.markdown - entity.name.section + +## Second Heading # +| <- markup.heading.2 punctuation.definition.heading +|^^^^^^^^^^^^^^^^^^^ markup.heading.2.markdown +|^^ - entity.name.section +| ^^^^^^^^^^^^^^ entity.name.section +| ^^ - entity.name.section +| ^ punctuation.definition.heading.end.markdown + +https://spec.commonmark.org/0.30/#example-71 + + ## Heading ## +|^^^^^^^^^^^^^^^ meta.block-level.markdown markup.heading.2.markdown +|^ - punctuation +| ^^ punctuation.definition.heading.begin.markdown +| ^^^^^^^^^ - punctuation +| ^^ punctuation.definition.heading.end.markdown +| ^ - punctuation +|^^^^ - entity.name.section +| ^^^^^^^ entity.name.section.markdown +| ^^^^ - entity.name.section + +https://spec.commonmark.org/0.30/#example-73 +## Example 73 (trailing spaces!) ##### +| ^ punctuation.definition.heading.end.markdown +| ^ meta.whitespace.newline.markdown + +https://spec.commonmark.org/0.30/#example-74 +## Example 74 #### > +|^^^^^^^^^^^^^^^^^^^^^^^ markup.heading.2.markdown +|^^ - entity.name.section +| ^^^^^^^^^^^^^^^^^^^^ entity.name.section.markdown +| ^ - entity.name.section + +https://spec.commonmark.org/0.30/#example-75 +# #heading# # +| <- markup.heading.1.markdown punctuation.definition.heading.begin.markdown +|^^^^^^^^^^^^^ meta.block-level.markdown markup.heading.1.markdown +|^ - entity.name.section +| ^^^^^^^^^ entity.name.section.markdown +| ^^ - entity.name.section +| ^ punctuation.definition.heading.end.markdown + +https://spec.commonmark.org/0.30/#example-76 +## heading \## +| <- markup.heading.2.markdown punctuation.definition.heading.begin.markdown +|^^^^^^^^^^^^^^ meta.block-level.markdown markup.heading.2.markdown +|^^ - entity +| ^^^^^^^^^^^ entity.name.section.markdown +| ^^ constant.character.escape.markdown +| ^^^ - punctuation +| ^ - entity.name.section + +https://spec.commonmark.org/0.30/#example-79 +# +| <- markup.heading.1.markdown punctuation.definition.heading.begin.markdown + +# # +| <- markup.heading.1.markdown punctuation.definition.heading.begin.markdown +|^^^ meta.block-level.markdown markup.heading.1.markdown - entity.name.section +| ^ punctuation.definition.heading.end.markdown + +## +| <- markup.heading.2.markdown punctuation.definition.heading.begin.markdown - entity.name.section +|^ markup.heading.2.markdown punctuation.definition.heading.begin.markdown - entity.name.section + +## ## +| <- markup.heading.2.markdown punctuation.definition.heading.begin.markdown - entity.name.section +|^^^^^ meta.block-level.markdown markup.heading.2.markdown - entity.name.section +|^ punctuation.definition.heading.begin.markdown +| ^^ punctuation.definition.heading.end.markdown + +### ### +| <- meta.block-level.markdown markup.heading.3.markdown - entity.name.sectionpunctuation.definition.heading.begin.markdown +|^^^^^^^ meta.block-level.markdown markup.heading.3.markdown - entity.name.section +|^^ punctuation.definition.heading.begin.markdown +| ^^^ punctuation.definition.heading.end.markdown + +# #### # +| <- markup.heading.1.markdown punctuation.definition.heading.begin.markdown +|^^^^^^^^ meta.block-level.markdown markup.heading.1.markdown +|^ - entity.name.section +| ^^^^ entity.name.section.markdown +| ^^ - entity.name.section +| ^ punctuation.definition.heading.end.markdown + +## #### ## +| <- markup.heading.2.markdown punctuation.definition.heading.begin.markdown +|^^^^^^^^^^ meta.block-level.markdown markup.heading.2.markdown +|^ - entity.name.section +| ^^^^ entity.name.section.markdown +| ^^^ - entity.name.section +| ^^ punctuation.definition.heading.end.markdown + +#NotAHeading +| <- - markup.heading +|^^^^^^^^^^^^ - markup.heading + +Headings terminate paragraphs +# Heading +| <- markup.heading.1.markdown punctuation.definition.heading.begin.markdown - markup.bold +|^^^^^^^^ markup.heading.1.markdown + +Headings terminate **bold text +# Heading +| <- markup.heading.1.markdown punctuation.definition.heading.begin.markdown - markup.bold +|^^^^^^^^ markup.heading.1.markdown +this must not be bold** +| <- - meta.bold +|^^^^^^^^^^^^^^^^^^^^^^^^ - meta.bold + +Headings terminate *italic text +# Heading +| <- markup.heading.1.markdown punctuation.definition.heading.begin.markdown - markup.italic +|^^^^^^^^ markup.heading.1.markdown +this must not be italic* +| <- - meta.italic +|^^^^^^^^^^^^^^^^^^^^^^^ - meta.italic + +Headings terminate ***bold italic text +# Heading +| <- markup.heading.1.markdown punctuation.definition.heading.begin.markdown - markup.bold - markup.italic +|^^^^^^^^ markup.heading.1.markdown +this must not be bold italic*** +| <- - meta.bold - markup.italic +|^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - meta.bold - markup.italic + +Alternate Heading +================= +|^^^^^^^^^^^^^^^^ markup.heading.1 punctuation.definition +| ^ meta.whitespace.newline + +heading underlined with dashes +------------------------------ +| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ markup.heading.2 punctuation.definition.heading + +underlined heading followed by a separator +------------------- +------ +| <- meta.block-level meta.separator - markup.heading + +underlined heading followed by another one that should be treated as a normal paragraph +================== +===== +| <- - markup.heading + +``` +Fenced codeblocks are no no setext heading +``` +--- +| <- meta.separator.thematic-break.markdown punctuation.definition.thematic-break.markdown +|^^ meta.separator.thematic-break.markdown punctuation.definition.thematic-break.markdown + + +Paragraph of text that should be scoped as meta.paragraph. +|^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ meta.paragraph +A [link](https://example.com){ :_attr = value }, *italic text* and **bold**. +| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ meta.link.inline +| ^ punctuation.definition.link.begin +| ^ punctuation.definition.link.end +| ^ punctuation.definition.metadata +| ^^^^^^^^^^^^^^^^^^^ markup.underline.link +| ^ punctuation.definition.metadata +| ^ punctuation.definition.attributes.begin.markdown +| ^^^^^^^^^^^^^^ meta.attribute-with-value.markdown +| ^^^^^^ entity.other.attribute-name.markdown +| ^ punctuation.separator.key-value.markdown +| ^^^^^ string.unquoted.markdown +| ^ punctuation.definition.attributes.end.markdown +| ^^^^^^^^^^^^^ markup.italic +| ^ punctuation.definition.italic +| ^ punctuation.definition.italic +| ^^ punctuation.definition.bold +| ^^^^^^^^ markup.bold +| ^^ punctuation.definition.bold + +Inline `code sample`. +| ^^^^^^^^^^^^^ markup.raw.inline +| ^ punctuation.definition.raw +| ^ punctuation.definition.raw + +Here is a [](https://example.com). +| ^^ meta.link.inline +| ^ punctuation.definition.link.begin +| ^ punctuation.definition.link.end +| ^ punctuation.definition.metadata +| ^^^^^^^^^^^^^^^^^^^ markup.underline.link +| ^ punctuation.definition.metadata + +Here is a [](https://example.com){_attr="value"}. +| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ meta.link.inline +| ^ punctuation.definition.link.begin +| ^ punctuation.definition.link.end +| ^ punctuation.definition.metadata +| ^^^^^^^^^^^^^^^^^^^ markup.underline.link +| ^ punctuation.definition.metadata +| ^ punctuation.definition.attributes.begin.markdown +| ^^^^^^^^^^^^^ meta.attribute-with-value.markdown +| ^^^^^ entity.other.attribute-name.markdown +| ^ punctuation.separator.key-value.markdown +| ^^^^^^^ string.quoted.double.markdown +| ^ punctuation.definition.attributes.end.markdown + +Here is a [reference link][name]. +| ^^^^^^^^^^^^^^^^^^^^^^ meta.link.reference +| ^ punctuation.definition.constant.begin +| ^^^^ constant.other.reference.link +| ^ punctuation.definition.constant.end + +Here is a [reference link][name]{_attr='value' :att2}. +| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ meta.link.reference +| ^ punctuation.definition.constant.begin +| ^^^^ constant.other.reference.link +| ^ punctuation.definition.constant.end +| ^ punctuation.definition.attributes.begin.markdown +| ^^^^^ entity.other.attribute-name.markdown +| ^ punctuation.separator.key-value.markdown +| ^^^^^^^ string.quoted.single.markdown +| ^^^^^ entity.other.attribute-name.markdown +| ^ punctuation.definition.attributes.end.markdown + +Here is a [blank reference link][]{}. +| ^^^^^^^^^^^^^^^^^^^^^^^^^^ meta.link.reference +| ^ punctuation.definition.constant.begin +| ^ punctuation.definition.constant.end +| ^ punctuation.definition.attributes.begin.markdown +| ^ punctuation.definition.attributes.end.markdown + +Here is a footnote[^1][link][] or long[^longnote][link][]. +| ^^^^ meta.link.reference.footnote.markdown-extra +| ^^^^^^^^ meta.link.reference.literal +| ^^^^^^^^^^^ meta.link.reference.footnote.markdown-extra +| ^^^^^^^^ meta.link.reference.literal + +Here is a ![](https://example.com/cat.gif). +| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ meta.image.inline +| ^ punctuation.definition.image.begin +| ^ punctuation.definition.image.end - string +| ^ punctuation.definition.metadata +| ^^^^^^^^^^^^^^^^^^^^^^^^^^^ markup.underline.link.image +| ^ punctuation.definition.metadata + +Here is a ![](https://example.com/cat.gif){_at"r=value :att2}. +| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ meta.image.inline +| ^ punctuation.definition.image.begin +| ^ punctuation.definition.image.end - string +| ^ punctuation.definition.metadata +| ^^^^^^^^^^^^^^^^^^^^^^^^^^^ markup.underline.link.image +| ^ punctuation.definition.metadata +| ^ punctuation.definition.attributes.begin.markdown +| ^^^^^ entity.other.attribute-name.markdown +| ^ invalid.illegal.attribute-name.markdown +| ^ punctuation.separator.key-value.markdown +| ^^^^^ string.unquoted.markdown +| ^^^^^ entity.other.attribute-name.markdown +| ^ punctuation.definition.attributes.end.markdown + +Here is a ![Image Alt Text](https://example.com/cat.gif). +| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ meta.image.inline +| ^ punctuation.definition.image.begin +| ^ punctuation.definition.image.end - string +| ^ punctuation.definition.metadata +| ^^^^^^^^^^^^^^^^^^^^^^^^^^^ markup.underline.link.image +| ^ punctuation.definition.metadata + +Here is a ![Image Alt Text]( https://example.com/cat.gif ). +| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ meta.image.inline +| ^ punctuation.definition.image.begin +| ^ punctuation.definition.image.end - string +| ^ punctuation.definition.metadata +| ^^^^^^^^^^^^^^^^^^^^^^^^^^^ markup.underline.link.image +| ^ punctuation.definition.metadata + +Here is a ![Image Alt Text]( + https://example.com/cat.gif ). +| ^^^^^^^^^^^^^^^^^^^^^^^^^^^ markup.underline.link.image +| ^ punctuation.definition.metadata + +Here is a ![Image Alt Text]( + https://example.com/cat.gif + "hello" ). +|^^^^^^^ meta.image.inline string.other.link.description.title +| ^^^^ meta.image.inline +| ^ punctuation.definition.metadata.end + +Here is a ![Image Alt Text]( + "hello" ). +| ^ punctuation.definition.link.begin +| ^^^^^^^^^^^^^^^^^^^^^^^^^^^ markup.underline.link.image +| ^ punctuation.definition.link.end +| ^^^^^^^ string.other.link.description.title +|^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ meta.paragraph meta.image.inline +| ^ punctuation.definition.metadata.end + +Here is a ![Image Alt Text]( + (hello) ). +| ^ punctuation.definition.link.begin +| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ markup.underline.link.image +| ^ invalid.illegal.unexpected-whitespace +| ^ invalid.illegal.unexpected-whitespace +| ^ punctuation.definition.link.end +| ^^^^^^^ string.other.link.description.title +|^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ meta.paragraph meta.image.inline +| ^ punctuation.definition.metadata.end + +Here is a ![Image Alt Text]( + https://example .com /cat.gif (hello) ). +| ^^^^^^^^^^^^^^^ markup.underline.link.image +| ^ invalid.illegal.unexpected-whitespace +| ^^^^ markup.underline.link.image +| ^ invalid.illegal.unexpected-whitespace +| ^^^^^^^^ markup.underline.link.image +| ^^^^^^^ string.other.link.description.title +|^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ meta.paragraph meta.image.inline +| ^ punctuation.definition.metadata.end + +Here is a ![Image Ref Alt][1]. +| ^^^^^^^^^^^^^^^^^^^ meta.image.reference +| ^^ punctuation.definition.image.begin +| ^ punctuation.definition.image.end +| ^ punctuation.definition.constant +| ^ constant.other.reference.link +| ^ punctuation.definition.constant + +now you can access the [The Ever Cool Site: Documentation about Sites]( + www.thecoolsite.com.ca/documentations/about/cool ) for more information about... +| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ meta.link.inline markup.underline.link +| ^ - invalid +| ^ meta.link.inline punctuation.definition.metadata.end + +now you can access the [The Ever Cool Site: Documentation about Sites]( + www.thecoolsite.com.ca /documentations/about/cool ) for more information about... +| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ meta.paragraph meta.link.inline +| ^^^^^^^^^^^^^^^^^^^^^^ markup.underline.link +| ^ invalid.illegal.unexpected-whitespace +| ^^^^^^^^^^^^^^^^^^^^^^^^^^ markup.underline.link +| ^ - invalid +| ^ punctuation.definition.metadata.end + +now you can access the [The Ever Cool Site: Documentation about Sites]( + www.thecoolsite.com.ca/documentations/about/cool + (title)) for more information about... +| ^^^^^^^^ meta.paragraph meta.link.inline +| ^ punctuation.definition.metadata.end +| ^^^^^^^ string.other.link.description.title.markdown + + 1. Ordered list item +| ^^^^^^^^^^^^^^^^^^^^^ markup.list.numbered +| ^^ markup.list.numbered.bullet - markup.list.numbered markup.list.numbered +| ^ punctuation.definition.list_item + 2. Ordered list item #2 +| ^^^^^^^^^^^^^^^^^^^^^^^^ markup.list.numbered - markup.list.numbered markup.list.numbered +| ^^ markup.list.numbered.bullet +| ^ punctuation.definition.list_item + 1. Subitem + 2. Another subitem +|^^^^^^^^^^^^^^^^^^^^^^^ markup.list.numbered +| ^^ markup.list.numbered.bullet +| ^ punctuation.definition.list_item +| ^^^^^^^^^^^^^^^^ meta.paragraph.list - meta.paragraph.list meta.paragraph.list + +Paragraph break. + + - Unordered list item +| ^^^^^^^^^^^^^^^^^^^^ markup.list.unnumbered - markup.list.unnumbered markup.list.unnumbered +| ^ markup.list.unnumbered.bullet punctuation.definition.list_item + - Unordered list item #2 +| ^^^^^^^^^^^^^^^^^^^^^^^ markup.list.unnumbered - markup.list.unnumbered markup.list.unnumbered +| ^ markup.list.unnumbered.bullet punctuation.definition.list_item + +Paragraph break. + +- `` | `` (components/Logo.vue) +- `` | `` | (components/my-component.vue) +| <- markup.list.unnumbered.bullet.markdown punctuation.definition.list_item.markdown +| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ markup.list.unnumbered.markdown meta.paragraph.list.markdown + +Paragraph break. + + * Unordered list item +| ^^^^^^^^^^^^^^^^^^^^ markup.list.unnumbered - markup.list.unnumbered markup.list.unnumbered +| ^ markup.list.unnumbered.bullet punctuation.definition.list_item + + Unordered list item #2 +| ^^^^^^^^^^^^^^^^^^^^^^ markup.list.unnumbered - markup.list.unnumbered markup.list.unnumbered +| ^ markup.list.unnumbered.bullet punctuation.definition.list_item + + Subitem 1 +| ^ punctuation.definition.list_item + + Item + + Subitem + + Another subitem +| ^ markup.list.unnumbered.bullet punctuation.definition.list_item - meta.paragraph.list +| ^^^^^^^^^^^^^^^ meta.paragraph.list + + Nested Subitem +| ^ markup.list.unnumbered.bullet punctuation.definition.list_item - markup.list.unnumbered markup.list.unnumbered + + Nested + Subitem +| ^ markup.list.unnumbered.bullet punctuation.definition.list_item +| ^ - punctuation.definition.list_item + + * Unsorted list item + ```xml +|^^^ markup.list.unnumbered.markdown meta.paragraph.list.markdown meta.code-fence.definition.begin.xml.markdown-gfm punctuation.definition.raw.code-fence.begin.markdown +| ^^ markup.list.unnumbered.markdown meta.paragraph.list.markdown meta.code-fence.definition.begin.xml.markdown-gfm constant.other.language-name.markdown + +|^^^^^ markup.list.unnumbered.markdown meta.paragraph.list.markdown markup.raw.code-fence.xml.markdown-gfm text.xml meta.tag.xml + ``` +|^^^ markup.list.unnumbered.markdown meta.paragraph.list.markdown meta.code-fence.definition.end.xml.markdown-gfm punctuation.definition.raw.code-fence.end.markdown + +Paragraph break. + +> This is a block quote. It contains markup. +> Including things like *italics* +|^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ markup.quote +| ^^^^^^^^^ markup.italic + +Paragraph break. + +--- +|^^^ meta.block-level meta.separator.thematic-break +|^^ punctuation.definition.thematic-break + +Paragraph break. + +-------- +|^^^^^^^^ meta.block-level meta.separator.thematic-break +|^^^^^^^ punctuation.definition.thematic-break + +[1]: https://google.com +| <- meta.link.reference.def +|^^^^^^^^^^^^^^^^^^^^^^ meta.link.reference.def +|^ entity.name.reference.link +| ^ punctuation.separator.key-value +| ^^^^^^^^^^^^^^^^^^ markup.underline.link + +
this is HTML until there are two blank lines
+| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ meta.disable-markdown +disabled markdown +| <- meta.disable-markdown + +non-disabled markdown +| <- - meta.disable-markdown + +
this is HTML until there are two blank lines +| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ meta.disable-markdown +still HTML +| ^^^^ meta.tag.inline.any.html entity.name.tag.inline.any.html +
+| ^^^^ meta.disable-markdown + +non-disabled markdown +| <- - meta.disable-markdown + +
nested tags don't count 
test
+| ^^^^^^ meta.disable-markdown meta.tag.block.any.html +non-disabled markdown +| <- - meta.disable-markdown + +
nested tags don't count
test +| ^^^^^ meta.disable-markdown +
+| ^^^ meta.disable-markdown entity.name.tag.block.any.html + +non-disabled markdown +| <- - meta.disable-markdown + +
two blank lines needed
to stop disabled markdown +| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ meta.disable-markdown +disabled markdown +| <- meta.disable-markdown + +non-disabled markdown +| <- - meta.disable-markdown + +
another
disable test +| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ meta.disable-markdown +| ^^^^^^ meta.tag.inline.any.html +disabled markdown +| <- meta.disable-markdown + +non-disabled markdown +| <- - meta.disable-markdown + +*a* +| ^ markup.italic +

*a*

+| ^^^^^^^^^ meta.disable-markdown - markup.italic +*a* +| ^^ meta.disable-markdown + +non-disabled markdown +| <- - meta.disable-markdown + + +# Block Quote Tests ########################################################### + +>= +| <- punctuation.definition.blockquote.markdown + +>== +| <- punctuation.definition.blockquote.markdown + + >= +| ^ punctuation.definition.blockquote.markdown + >= +| ^^ - punctuation.definition.blockquote.markdown + + >= +| ^^ - punctuation.definition.blockquote.markdown + +> Block quote +| <- meta.block-level markup.quote punctuation.definition.blockquote +| ^^^^^^^^^^^ meta.block-level markup.quote + +> Block quote followed by an empty block quote line +> +| <- meta.block-level markup.quote punctuation.definition.blockquote + +> Block quote followed by an empty block quote line +> +> Followed by more quoted text +| <- meta.block-level markup.quote punctuation.definition.blockquote + +> > Nested block quote +| <- meta.block-level markup.quote punctuation.definition.blockquote +| ^^^^^^^^^^^^^^^^^^^^^ meta.block-level.markdown markup.quote.markdown markup.quote.markdown +|^ - punctuation +| ^ punctuation.definition.blockquote +| ^ - punctuation + +> > Nested quote +> Followed by more quoted text that is not nested +| <- meta.block-level markup.quote punctuation.definition.blockquote - markup.quote markup.quote + +> Here is a block quote +This quote continues on. Line breaking is OK in markdown +| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ meta.block-level markup.quote +> Here it is again +| <- punctuation.definition.blockquote + +paragraph +| <- meta.paragraph - meta.block-level + +> > this is a nested quote but no code in a block quote +| <- punctuation.definition.blockquote +| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ meta.block-level.markdown markup.quote.markdown markup.quote.markdown + +> > this is code in a block quote, not a nested quote +| <- punctuation.definition.blockquote +| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ markup.raw.block - markup.quote markup.quote + +> CommonMark expects following line to be indented code block (see: example 326) + > but all common parsers handle it as continued text. +| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ meta.block-level.markdown markup.quote.markdown - markup.raw +| ^ - punctuation + +> Quoted fenced code block begin +> ``` +| <- meta.block-level.markdown markup.quote.markdown punctuation.definition.blockquote.markdown +|^ meta.block-level.markdown markup.quote.markdown - meta.code-fence +| ^^^^ meta.block-level.markdown markup.quote.markdown meta.code-fence.definition.begin.text.markdown-gfm +| ^^^ punctuation.definition.raw.code-fence.begin.markdown + +> Quoted fenced code block language identifier +> ```C++ +| <- meta.block-level.markdown markup.quote.markdown punctuation.definition.blockquote.markdown +|^ meta.block-level.markdown markup.quote.markdown - meta.code-fence +| ^^^^^^^ meta.block-level.markdown markup.quote.markdown meta.code-fence.definition.begin.text.markdown-gfm +| ^^^ constant.other.language-name.markdown + +> Quoted fenced code block language identifier +> ```C++ info string +| <- meta.block-level.markdown markup.quote.markdown punctuation.definition.blockquote.markdown +|^ meta.block-level.markdown markup.quote.markdown - meta.code-fence +| ^^^^^^^^^^^^^^^^^^^ meta.block-level.markdown markup.quote.markdown meta.code-fence.definition.begin.text.markdown-gfm +| ^^^ constant.other.language-name.markdown +| ^^^^^^^^^^^^^ - constant + +> Quoted fenced code block content +> ``` +> code block +| <- meta.block-level.markdown markup.quote.markdown punctuation.definition.blockquote.markdown +|^ meta.block-level.markdown markup.quote.markdown - meta.code-fence +| ^^^^^^^^^^^ meta.block-level.markdown markup.quote.markdown markup.raw.code-fence.markdown-gfm + +> Quoted fenced code block end +> ``` +> ``` +| <- meta.block-level.markdown markup.quote.markdown punctuation.definition.blockquote.markdown +|^ meta.block-level.markdown markup.quote.markdown - meta.code-fence +| ^^^^ meta.block-level.markdown markup.quote.markdown meta.code-fence.definition.end.text.markdown-gfm +| ^^^ punctuation.definition.raw.code-fence.end.markdown + +> > 2nd level quoted fenced code block +> > ``` +> > code block ``` +> > ``` +| <- meta.block-level.markdown markup.quote.markdown markup.quote.markdown punctuation.definition.blockquote.markdown +|^^^ meta.block-level.markdown markup.quote.markdown markup.quote.markdown - meta.code-fence +| ^^^^ meta.block-level.markdown markup.quote.markdown markup.quote.markdown meta.code-fence.definition.end.text.markdown-gfm + +> Block quote followed by fenced code block +``` +| <- meta.code-fence.definition.begin.text.markdown-gfm punctuation.definition.raw.code-fence.begin.markdown - meta.quote +``` +| <- meta.code-fence.definition.end.text.markdown-gfm punctuation.definition.raw.code-fence.end.markdown - meta.quote + +> Quoted fenced code block is terminated by missing > at bol +> ``` +no code block +| <- meta.paragraph.markdown - meta.quote - meta.code-fence +|^^^^^^^^^^^^^ meta.paragraph.markdown - meta.quote - meta.code-fence + +> Quoted fenced code block is terminated by missing > at bol +> ``` +> content +no code block +| <- meta.paragraph.markdown - meta.quote - meta.code-fence +|^^^^^^^^^^^^^ meta.paragraph.markdown - meta.quote - meta.code-fence + +> Unterminated quoted fenced code block followed by unquoted fenced code block +> ``` +``` +| <- meta.code-fence.definition.begin.text.markdown-gfm - markup.quote +``` +| <- meta.code-fence.definition.end.text.markdown-gfm - markup.quote + +> Block quote followed by heading +# heading +| <- meta.block-level.markdown markup.heading.1.markdown punctuation.definition.heading.begin.markdown +|^^^^^^^^^ meta.block-level.markdown markup.heading.1.markdown - meta.quote +| ^^^^^^^ entity.name.section.markdown + +> Block quote followed by list +* list item +| <- markup.list.unnumbered.bullet.markdown punctuation.definition.list_item.markdown +|^^^^^^^^^^^ markup.list.unnumbered.markdown - meta.quote + +> Block quote followed by list ++ list item +| <- markup.list.unnumbered.bullet.markdown punctuation.definition.list_item.markdown +|^^^^^^^^^^^ markup.list.unnumbered.markdown - meta.quote + +> Block quote followed by list +- list item +| <- markup.list.unnumbered.bullet.markdown punctuation.definition.list_item.markdown +|^^^^^^^^^^^ markup.list.unnumbered.markdown - meta.quote + +> Block quote followed by list +1. list item +| <- markup.list.numbered.bullet.markdown - punctuation +|^ markup.list.numbered.bullet.markdown punctuation.definition.list_item.markdown +| ^^^^^^^^^^ markup.list.numbered.markdown - meta.quote + +> Block quote followed by thematic break +*** +| <- meta.block-level.markdown meta.separator.thematic-break.markdown punctuation.definition.thematic-break.markdown - meta.quote + +> Block quote followed by thematic break +- - - +| <- meta.block-level.markdown meta.separator.thematic-break.markdown punctuation.definition.thematic-break.markdown - meta.quote + +Code block below: + + this is code! +| ^^^^^^^^^^^^^^^^ meta.block-level markup.raw.block + + more code + spanning multiple lines +| ^^^^^^^^^^^^^^^^^^^^^^^^^^ meta.block-level markup.raw.block + +paragraph +| <- meta.paragraph - meta.block-level + +- - - - +| ^^^^^^ meta.block-level meta.separator +| ^ punctuation.definition.thematic-break +| ^ punctuation.definition.thematic-break +| ^ punctuation.definition.thematic-break +| ^ - punctuation +* * * * * +| ^^^^^^^^ meta.block-level meta.separator + +_ _ _ _ _ _ _ +| ^^^^^^^^^^^^ meta.block-level meta.separator +| ^ punctuation.definition.thematic-break +| ^ punctuation.definition.thematic-break +| ^ - punctuation + +- - - - +| <- meta.block-level meta.separator.thematic-break punctuation.definition.thematic-break +|^^ - punctuation +| ^ punctuation +| ^ punctuation + + +| ^^^^^^^^^^^^^^^^^^^^^^^^ meta.paragraph meta.link.email.lt-gt markup.underline.link + +| ^^^^^^^^^^^^^^^^^^^ meta.paragraph meta.link.inet markup.underline.link + +| ^^^^^^^^^^^^^^^^ meta.paragraph meta.link.inet markup.underline.link + +| ^^^^^^^^^^^^^^ meta.paragraph meta.link.inet markup.underline.link + +Visit www.commonmark.org/help for more information. +| ^^^^^^^^^^^^^^^^^^^^^^^ markup.underline.link +| ^^^^^^^^^^^^^^^^^^^^^^^ - markup.underline.link +Visit www.commonmark.org. +| ^^^^^^^^^^^^^^^^^^ meta.paragraph markup.underline.link +| ^^ - markup.underline.link +Visit www.commonmark.org/a.b. +| ^^^^^^^^^^^^^^^^^^^^^^ meta.paragraph markup.underline.link +| ^ - markup.underline.link +www.google.com/search?q=(business))+ok +|^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ markup.underline.link +| ^ - markup.underline.link +www.google.com/search?q=Markup+(business) +|^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ markup.underline.link +www.commonmark.org/he +|^^^^^^^^^^^^^^^^^^^^ markup.underline.link +| ^ - markup.underline.link +http://commonmark.org +|^^^^^^^^^^^^^^^^^^^^ markup.underline.link +www.google.com/search?q=commonmark&hl=en +|^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ markup.underline.link +| ^ - markup.underline.link +www.google.com/search?q=commonmark&hl; +|^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ markup.underline.link +| ^^^^ constant.character.entity.named.html - markup.underline.link +(Visit https://encrypted.google.com/search?q=Markup+(business)) +| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ markup.underline.link +| ^^ - markup.underline.link +Anonymous FTP is available at ftp://foo.bar.baz. +| ^^^^^^^^^^^^^^^^^ markup.underline.link +| ^^ - markup.underline.link +(see http://www.google.com/search?q=commonmark&hl=en) +| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ markup.underline.link +| ^^ - markup.underline.link + +foo@bar.baz +|^^^^^^^^^^ markup.underline.link +hello@mail+xyz.example isn't valid, but hello+xyz@mail.example is. +|^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - markup.underline.link +| ^^^^^^^^^^^^^^^^^^^^^^ markup.underline.link + a.b-c_d@a.b +|^^^^^^^^^^^ markup.underline.link +| ^ - markup.underline.link +a.b-c_d@a.b. +|^^^^^^^^^^ markup.underline.link +| ^^ - markup.underline.link + a.b-c_d@a.b- +|^^^^^^^^^^^^^ - markup.underline.link + a.b-c_d@a.b_ +|^^^^^^^^^^^^^ - markup.underline.link + test@test.test.me +|^^^^^^^^^^^^^^^^^ markup.underline.link + +this is a raw ampersand & does not require HTML escaping +| ^ meta.other.valid-ampersand + +this is a raw bracket < > does not require HTML escaping +| ^^^ - meta.tag +| ^ meta.other.valid-bracket +| ^ - meta.other.valid-bracket + +these are raw ligatures << <<< <<<< <<<<< >>>>> >>>> >>> >> +| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - meta.other.valid-bracket - meta.tag + +these are raw ligatures <- <-- <--- <---- <-< <--< <---< <----< +| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - meta.other.valid-bracket - meta.tag + +these are raw ligatures -> --> ---> ----> >-> >--> >---> >----> +| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - meta.other.valid-bracket - meta.tag + +these are raw ligatures >- >-- >--- >---- ----< ---< --< -< +| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - meta.other.valid-bracket - meta.tag + +these are raw ligatures >< >-< >--< >---< <---> <--> <-> <> +| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - meta.other.valid-bracket - meta.tag + +these are raw ligatures <= <== <=== <==== <=< <==< <===< <====< +| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - meta.other.valid-bracket - meta.tag + +these are raw ligatures => ==> ===> ====> >=> >==> >===> >====> +| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - meta.other.valid-bracket - meta.tag + +these are raw ligatures >= >== >=== >==== ====< ===< ==< =< +| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - meta.other.valid-bracket - meta.tag + +these are raw ligatures >< >=< >==< >===< <===> <==> <=> <> +| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - meta.other.valid-bracket - meta.tag + +these are raw ligatures - -- --- ---- ----- ===== ==== === == = +| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - meta.other.valid-bracket - meta.tag + +[2]: https://github.com/sublimehq/Packages "Packages Repo" +| <- meta.link.reference.def +|^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ meta.link.reference.def +|^ entity.name.reference.link +| ^ punctuation.separator.key-value +| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ markup.underline.link +| ^^^^^^^^^^^^^^^ string.other.link.description.title +| ^ punctuation.definition.string.begin +| ^ punctuation.definition.string.end + +[3]: https://github.com/sublimehq/Packages/issues/ 'Issues on Packages Repo' +| <- meta.link.reference.def +|^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ meta.link.reference.def +|^ entity.name.reference.link +| ^ punctuation.separator.key-value +| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ markup.underline.link +| ^^^^^^^^^^^^^^^^^^^^^^^^^ string.other.link.description.title +| ^ punctuation.definition.string.begin +| ^ punctuation.definition.string.end + +Paragraph followed immediately by a list, no blank line in between +- list item 1 +| <- markup.list.unnumbered punctuation.definition.list_item + +Paragraph followed immediately by a numbered list, no blank line in between + 1. list item 1 +|^^^^^^^^^^^^^^^ markup.list.numbered +|^^ markup.list.numbered.bullet +| ^ punctuation.definition.list_item +| ^^^^^^^^^^^^ meta.paragraph.list + more text - this punctuation should be ignored 2. +|^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ markup.list.numbered meta.paragraph.list +| ^ - punctuation.definition.list_item +| ^ - punctuation.definition.list_item + +Paragraph not followed immediately by a numbered list, +because it doesn't begin with the number one: + 2. text +| ^ - markup.list.numbered - punctuation.definition.list_item + + +> Block quote with list items +> - list item 1 +| ^ meta.block-level markup.quote punctuation.definition.list_item +> - list item 2 +| ^ markup.list.unnumbered.bullet punctuation.definition.list_item +| ^^^^^^^^^^^^^^ meta.block-level markup.quote markup.list.unnumbered +| ^^^^^^^^^^^^ meta.paragraph.list +> 1. sub list item +| <- meta.block-level markup.quote punctuation.definition.blockquote +|^^^^^^^^^^^^^^^^^^^^ meta.block-level markup.quote +| ^ punctuation.definition.list_item +| ^^ markup.list.numbered.bullet +| ^^^^^^^^^^^^^^^^^^^ markup.list.numbered +| ^^^^^^^^^^^^^^ meta.paragraph.list +> - list item 3 + continued +| ^^^^^^^^^^ meta.block-level.markdown markup.quote.markdown markup.list.unnumbered.markdown meta.paragraph.list.markdown + +* this is a list + + > This is a blockquote. +| ^ markup.list.unnumbered markup.quote punctuation.definition.blockquote + + This is a paragraph still part of the + list item +| ^^^^^^^^^ markup.list.unnumbered meta.paragraph.list - meta.paragraph.list meta.paragraph.list + +* Lorem ipsum + + This is a code block +| ^^^^^^^^^^^^^^^^^^^^^^^^^^^ markup.list.unnumbered markup.raw.block +* list continues +| <- markup.list.unnumbered punctuation.definition.list_item - markup.raw.block +* list continues +* [ ] Unticked GitHub-flavored-markdown checkbox +|^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ markup.list.unnumbered +| ^ markup.checkbox.begin.markdown-gfm punctuation.definition.checkbox.begin.markdown-gfm +| ^ markup.checkbox.mark.markdown-gfm - punctuation +| ^ markup.checkbox.end.markdown-gfm punctuation.definition.checkbox.end.markdown-gfm +* [x] Ticked GFM checkbox +| ^ markup.checkbox.begin.markdown-gfm punctuation.definition.checkbox.begin.markdown-gfm +| ^ markup.checkbox.mark.markdown-gfm - punctuation +| ^ markup.checkbox.end.markdown-gfm punctuation.definition.checkbox.end.markdown-gfm +* [X] Another ticked checkbox +| ^ markup.checkbox.begin.markdown-gfm punctuation.definition.checkbox.begin.markdown-gfm +| ^ markup.checkbox.mark.markdown-gfm - punctuation +| ^ markup.checkbox.end.markdown-gfm punctuation.definition.checkbox.end.markdown-gfm + + [ ] Sub-item with checkbox +| ^ markup.checkbox.begin.markdown-gfm punctuation.definition.checkbox.begin.markdown-gfm +| ^ markup.checkbox.mark.markdown-gfm - punctuation +| ^ markup.checkbox.end.markdown-gfm punctuation.definition.checkbox.end.markdown-gfm +* [] Not a checkbox +| ^^^^^^^^^^^^^^^^^ - storage - constant +* [/] Not a checkbox +| ^^^^^^^^^^^^^^^^^^ - storage +* Not [ ] a [x] checkbox [X] +| ^^^^^^^^^^^^^^^^^^^^^^^^^^^ - storage - constant +* [ ] [Checkbox][] with next word linked +| ^ markup.checkbox.begin.markdown-gfm punctuation.definition.checkbox.begin.markdown-gfm +| ^ markup.checkbox.mark.markdown-gfm - punctuation +| ^ markup.checkbox.end.markdown-gfm punctuation.definition.checkbox.end.markdown-gfm +| ^^^^^^^^^^^^ meta.link +* list has `unclosed code +* list continues +| ^^^^^^^^^^^^^^^ - markup.raw + +> * [ ] task +| ^^^^^^^^^^^ meta.block-level.markdown markup.quote.markdown +| ^ markup.list.unnumbered.bullet.markdown +| ^^^^^^^^^^ markup.list.unnumbered.markdown +| ^ punctuation.definition.list_item.markdown +| ^ markup.checkbox.begin.markdown-gfm punctuation.definition.checkbox.begin.markdown-gfm +| ^ markup.checkbox.mark.markdown-gfm - punctuation +| ^ markup.checkbox.end.markdown-gfm punctuation.definition.checkbox.end.markdown-gfm +> * [x] task +| ^^^^^^^^^^^ meta.block-level.markdown markup.quote.markdown +| ^ markup.list.unnumbered.bullet.markdown +| ^^^^^^^^^^ markup.list.unnumbered.markdown +| ^ punctuation.definition.list_item.markdown +| ^ markup.checkbox.begin.markdown-gfm punctuation.definition.checkbox.begin.markdown-gfm +| ^ markup.checkbox.mark.markdown-gfm - punctuation +| ^ markup.checkbox.end.markdown-gfm punctuation.definition.checkbox.end.markdown-gfm +> * [X] task +| ^^^^^^^^^^^ meta.block-level.markdown markup.quote.markdown +| ^ markup.list.unnumbered.bullet.markdown +| ^^^^^^^^^^ markup.list.unnumbered.markdown +| ^ punctuation.definition.list_item.markdown +| ^ markup.checkbox.begin.markdown-gfm punctuation.definition.checkbox.begin.markdown-gfm +| ^ markup.checkbox.mark.markdown-gfm - punctuation +| ^ markup.checkbox.end.markdown-gfm punctuation.definition.checkbox.end.markdown-gfm +> * [X] task +> - [ ] task +| ^^^^^^^^^^^^^ meta.block-level.markdown markup.quote.markdown +| ^ markup.list.unnumbered.bullet.markdown +| ^^^^^^^^^^ markup.list.unnumbered.markdown +| ^ punctuation.definition.list_item.markdown +| ^ markup.checkbox.begin.markdown-gfm punctuation.definition.checkbox.begin.markdown-gfm +| ^ markup.checkbox.mark.markdown-gfm - punctuation +| ^ markup.checkbox.end.markdown-gfm punctuation.definition.checkbox.end.markdown-gfm + + +- `code` - +| ^ markup.list.unnumbered meta.paragraph.list markup.raw.inline punctuation.definition.raw +| ^^^^^^^^^^^^^^^^^^^ meta.tag.inline.a.html + 3. [see `demo`](#demo "demo") +| ^ punctuation.definition.list_item +| ^^^^^^^^^^^^^^^^^^^^^^^^^^ meta.link.inline +| ^^^^^^^^^^ meta.link.inline.description +| ^ punctuation.definition.metadata.begin +| ^ punctuation.definition.string.begin +| ^ punctuation.definition.string.end +| ^ punctuation.definition.metadata.end + [see `demo`](#demo (demo)) +| ^^^^^^^^^^^^^^^^^^^^^^^^^^ meta.link.inline +| ^^^^^^^^^^ meta.link.inline.description +| ^ punctuation.definition.metadata.begin +| ^ punctuation.definition.string.begin +| ^ punctuation.definition.string.end +| ^ punctuation.definition.metadata.end + [see `demo`](#demo 'demo') +| ^^^^^^^^^^^^^^^^^^^^^^^^^^ meta.link.inline +| ^^^^^^^^^^ meta.link.inline.description +| ^ punctuation.definition.metadata.begin +| ^ punctuation.definition.string.begin +| ^ punctuation.definition.string.end +| ^ punctuation.definition.metadata.end + Here is a ![example image](https://test.com/sublime.png "A demonstration"). +| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ markup.list.unnumbered meta.paragraph.list meta.image.inline +| ^^ punctuation.definition.image.begin +| ^^^^^^^^^^^^^ meta.image.inline.description +| ^ punctuation.definition.image.end +| ^ punctuation.definition.metadata +| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ markup.underline.link.image +| ^^^^^^^^^^^^^^^^^ string.other.link.description.title +| ^ punctuation.definition.string.begin +| ^ punctuation.definition.string.end +| ^ punctuation.definition.metadata + Here is a ![example image](https://test.com/sublime.png 'A demonstration'). +| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ markup.list.unnumbered meta.paragraph.list meta.image.inline +| ^^ punctuation.definition.image.begin +| ^^^^^^^^^^^^^ meta.image.inline.description +| ^ punctuation.definition.image.end +| ^ punctuation.definition.metadata +| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ markup.underline.link.image +| ^^^^^^^^^^^^^^^^^ string.other.link.description.title +| ^ punctuation.definition.string.begin +| ^ punctuation.definition.string.end +| ^ punctuation.definition.metadata + Here is a ![example image](https://test.com/sublime.png (A demonstration)). +| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ markup.list.unnumbered meta.paragraph.list meta.image.inline +| ^^ punctuation.definition.image.begin +| ^^^^^^^^^^^^^ meta.image.inline.description +| ^ punctuation.definition.image.end +| ^ punctuation.definition.metadata +| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ markup.underline.link.image +| ^^^^^^^^^^^^^^^^^ string.other.link.description.title +| ^ punctuation.definition.string.begin +| ^ punctuation.definition.string.end +| ^ punctuation.definition.metadata + +1) numberd item +| <- markup.list.numbered.bullet.markdown +|^ markup.list.numbered.bullet.markdown punctuation.definition.list_item.markdown +| ^^^^^^^^^^^^^^ markup.list.numbered.markdown + + 2) numberd item +| <- markup.list.numbered.markdown +|^^ markup.list.numbered.bullet.markdown +| ^^^^^^^^^^^^^^ markup.list.numbered.markdown + + 3) numberd item +| <- markup.list.numbered.markdown +|^ markup.list.numbered.markdown +| ^^ markup.list.numbered.bullet.markdown +| ^^^^^^^^^^^^^^ markup.list.numbered.markdown + + 4) numberd item +| <- markup.list.numbered.markdown +|^^ markup.list.numbered.markdown +| ^^ markup.list.numbered.bullet.markdown +| ^^^^^^^^^^^^^^ markup.list.numbered.markdown + + +| ^^^^^^^^^^^^^^^^^^^^^ comment.block.html + +*italic text HTML element end of italic text* +| <- punctuation.definition.italic +| ^ punctuation.definition.italic +| ^^^^^^ meta.tag.inline.any.html +| ^^^^^^^ meta.tag.inline.any.html + +_italic text HTML element end of italic text_ +| <- punctuation.definition.italic +| ^ punctuation.definition.italic +| ^^^^^^ meta.tag.inline.any.html +| ^^^^^^^ meta.tag.inline.any.html + +**bold text HTML element end of bold text** +| <- punctuation.definition.bold +| ^^ punctuation.definition.bold +| ^^^^^^ meta.tag.inline.any.html +| ^^^^^^^ meta.tag.inline.any.html + +__bold text HTML element end of bold text__ +| <- punctuation.definition.bold +| ^^ punctuation.definition.bold +| ^^^^^^ meta.tag.inline.any.html +| ^^^^^^^ meta.tag.inline.any.html + +*italic text HTML element end of italic text* +| <- punctuation.definition.italic +| ^ punctuation.definition.italic +| ^^^^^^ meta.tag.inline.any.html +| ^^^^^^^ meta.tag.inline.any.html + +_italic text HTML element end of italic text_ +| <- punctuation.definition.italic +| ^ punctuation.definition.italic +| ^^^^^^ meta.tag.inline.any.html +| ^^^^^^^ meta.tag.inline.any.html + +[link [containing] [square] brackets](#backticks) +|<- punctuation.definition.link.begin +|^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ meta.link.inline.description +| ^ punctuation.definition.link.end +[link `containing square] brackets] in backticks`[]](#wow) +| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ meta.link.inline.description +| ^ punctuation.definition.raw.begin +| ^ punctuation.definition.raw.end +| ^ punctuation.definition.link.end +[link ``containing square]` brackets[[][] in backticks``](#wow) +| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ meta.link.inline.description +| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ markup.raw.inline +| ^^ punctuation.definition.raw.begin +| ^^ punctuation.definition.raw.end +| ^ punctuation.definition.link.end +`inline markup ` +| ^^^^^^^^^^^^^ markup.raw.inline - meta.tag.inline.any.html +escaped backtick \`this is not code\` +| ^^ constant.character.escape +| ^^ constant.character.escape +| ^^^^^^^^^^^^^^^^ - markup.raw.inline + +http://spec.commonmark.org/0.28/#example-322 +*foo`*` +|^^^^^^^ markup.italic +| ^^^ markup.raw.inline + +| <- invalid.illegal.non-terminated.bold-italic + +http://spec.commonmark.org/0.28/#example-323 +[not a `link](/foo`) +|^^^^^^^^^^^^^^^^^^^ - meta.link +| ^^^^^^^^^^^^ markup.raw.inline + +http://spec.commonmark.org/0.28/#example-324 +`` +|^^^^^^^^^^ markup.raw.inline +| ^^ - markup.raw + +| <- invalid.illegal.non-terminated.raw + +http://spec.commonmark.org/0.28/#example-325 +` +| ^^^^^^^^^ meta.tag.inline.a +| ^ punctuation.definition.raw.begin + +| <- invalid.illegal.non-terminated.raw + +http://spec.commonmark.org/0.28/#example-326 +`` +|^^^^^^^^^^^^^^^^^ markup.raw.inline +| ^ punctuation.definition.raw.begin + +| <- invalid.illegal.non-terminated.raw + +http://spec.commonmark.org/0.28/#example-327 +` +|^^^^^^^^^^^^^^^^^^^ markup.underline.link +| ^ punctuation.definition.raw.begin + +| <- invalid.illegal.non-terminated.raw + +http://spec.commonmark.org/0.27/#example-328 +*foo bar* +| <- punctuation.definition.italic.begin +| ^ punctuation.definition.italic.end + +http://spec.commonmark.org/0.27/#example-329 +This is not emphasis, because the opening `*` is followed by whitespace, and hence not part of a left-flanking delimiter run: +a * foo bar* +| ^^^^^^^^^^^ - punctuation + +http://spec.commonmark.org/0.27/#example-332 +Intraword emphasis with `*` is permitted: +foo*bar* +| ^ punctuation.definition.italic.begin +| ^ punctuation.definition.italic.end +http://spec.commonmark.org/0.27/#example-333 +5*6*78 +|^ punctuation.definition.italic.begin +| ^ punctuation.definition.italic.end + +http://spec.commonmark.org/0.27/#example-334 +_foo bar_ +| <- punctuation.definition.italic.begin +| ^ punctuation.definition.italic.end + +http://spec.commonmark.org/0.27/#example-335 +This is not emphasis, because the opening `_` is followed by whitespace: +_ foo bar_ +| <- - punctuation +| ^^^^^^^^^ - punctuation + +http://spec.commonmark.org/0.27/#example-336 +This is not emphasis, because the opening `_` is preceded by an alphanumeric and followed by punctuation: +a_"foo"_ +|^^^^^^^^ - punctuation + +http://spec.commonmark.org/0.27/#example-337 +Emphasis with `_` is not allowed inside words: +foo_bar_ +| ^^^^^ - punctuation + +http://spec.commonmark.org/0.27/#example-338 +5_6_78 +|^^^^^ - punctuation + +http://spec.commonmark.org/0.27/#example-339 +пристаням_стремятся_ +| ^^^^^^^^^^^ - punctuation + +http://spec.commonmark.org/0.27/#example-341 +foo-_(bar)_ +| ^ punctuation.definition.italic.begin +| ^ punctuation.definition.italic.end + +*foo bar * +| <- punctuation.definition.italic.begin +| ^ - punctuation +* +| <- - punctuation +abc* +| ^ punctuation.definition.italic.end + +http://spec.commonmark.org/0.27/#example-347 +*foo*bar +| <- punctuation.definition.italic.begin +| ^ punctuation.definition.italic.end + +http://spec.commonmark.org/0.27/#example-348 +_foo bar _ +| <- punctuation.definition.italic.begin +| ^ - punctuation +_ +| <- - punctuation +abc_ +| ^ punctuation.definition.italic.end + +http://spec.commonmark.org/0.27/#example-351 +Intraword emphasis is disallowed for `_`: +_foo_bar +| <- punctuation.definition.italic.begin +| ^ - punctuation +abc_ +| ^ punctuation.definition.italic.end + +http://spec.commonmark.org/0.27/#example-353 +_foo_bar_baz_ +| <- punctuation.definition.italic.begin +| ^^^^^ - punctuation +| ^ punctuation.definition.italic.end + +http://spec.commonmark.org/0.27/#example-354 +_(bar)_. +| <- punctuation.definition.italic.begin +| ^ punctuation.definition.italic.end + +http://spec.commonmark.org/0.27/#example-355 + **foo bar** +|^^ punctuation.definition.bold.begin +| ^^ punctuation.definition.bold.end + +http://spec.commonmark.org/0.27/#example-356 +** foo bar** +| <- - punctuation +| ^^ - punctuation + +http://spec.commonmark.org/0.27/#example-358 +foo**bar** +| ^^ punctuation.definition.bold.begin +| ^^ punctuation.definition.bold.end + +http://spec.commonmark.org/0.27/#example-359 + __foo bar__ +|^^ punctuation.definition.bold.begin +| ^^ punctuation.definition.bold.end + +http://spec.commonmark.org/0.27/#example-360 +This is not strong emphasis, because the opening delimiter is followed by whitespace: +__ foo bar__ +| <- - punctuation +| ^^ - punctuation + +http://spec.commonmark.org/0.27/#example-361 +__ +| <- - punctuation + +http://spec.commonmark.org/0.27/#example-362 +a__"foo"__ +|^^^^^^^^^ - punctuation + +http://spec.commonmark.org/0.27/#example-363 +Intraword strong emphasis is forbidden with `__`: +foo__bar__ +| ^^^^^^^ - punctuation + +http://spec.commonmark.org/0.27/#example-364 +5__6__78 +|^^^^^^^ - punctuation + +http://spec.commonmark.org/0.27/#example-367 +foo-__(bar)__ +| ^^ punctuation.definition.bold.begin +| ^^ punctuation.definition.bold.end + +http://spec.commonmark.org/0.27/#example-368 +**foo bar ** +| <- punctuation.definition.bold.begin +| ^^ - punctuation +abc** +| ^^ punctuation.definition.bold.end + +http://spec.commonmark.org/0.27/#example-373 +Intraword emphasis: + **foo**bar +|^^ punctuation.definition.bold.begin +| ^^ punctuation.definition.bold.end + +http://spec.commonmark.org/0.27/#example-374 + __foo bar __ +|^^ punctuation.definition.bold.begin +| ^^ - punctuation +abc__ +| ^^ punctuation.definition.bold.end + +http://spec.commonmark.org/0.27/#example-376 +_(__foo__)_ +| <- punctuation.definition.italic.begin +| ^^ punctuation.definition.bold.begin +| ^^ punctuation.definition.bold.end +| ^ punctuation.definition.italic.end + +http://spec.commonmark.org/0.27/#example-377 +Intraword strong emphasis is forbidden with `__`: +__foo__bar +| <- punctuation.definition.bold.begin +| ^^ - punctuation +abc__ +| ^^ punctuation.definition.bold.end + +http://spec.commonmark.org/0.27/#example-379 +__foo__bar__baz__ +| <- punctuation.definition.bold.begin +| ^^ punctuation.definition.bold.end +| ^^^^^^^^^^ - punctuation + +http://spec.commonmark.org/0.27/#example-380 +This is strong emphasis, even though the closing delimiter is both left- and right-flanking, because it is followed by punctuation: +__(bar)__. +| <- punctuation.definition.bold.begin +| ^^ punctuation.definition.bold.end + +http://spec.commonmark.org/0.27/#example-381 +*foo [bar](/url)* +| <- punctuation.definition.italic.begin +| ^ punctuation.definition.italic.end +| ^^^^^^^^^^^ meta.link.inline + +http://spec.commonmark.org/0.27/#example-382 +*foo +| <- punctuation.definition.italic.begin +bar* +| ^ punctuation.definition.italic.end + +http://spec.commonmark.org/0.27/#example-383 +_foo __bar__ baz_ +| <- punctuation.definition.italic.begin +| ^^ punctuation.definition.bold.begin +| ^^ punctuation.definition.bold.end +| ^ punctuation.definition.italic.end + +http://spec.commonmark.org/0.27/#example-394 +** is not an empty emphasis +| <- - punctuation +|^ - punctuation + +http://spec.commonmark.org/0.27/#example-395 +**** is not an empty strong emphasis +| <- - punctuation +|^^^ - punctuation + +http://spec.commonmark.org/0.27/#example-396 +**foo [bar](/url)** +| <- punctuation.definition.bold.begin +| ^^^^^^^^^^^ meta.link.inline +| ^^ punctuation.definition.bold.end + +http://spec.commonmark.org/0.27/#example-397 +**foo +| <- punctuation.definition.bold.begin +bar** +| ^^ punctuation.definition.bold.end + +http://spec.commonmark.org/0.27/#example-398 +__foo _bar_ baz__ +| <- punctuation.definition.bold.begin +| ^ punctuation.definition.italic.begin +| ^ punctuation.definition.italic.end +| ^^ punctuation.definition.bold.end + +http://spec.commonmark.org/0.27/#example-408 +__ is not an empty emphasis +| <- - punctuation +|^ - punctuation + +http://spec.commonmark.org/0.27/#example-409 +____ is not an empty strong emphasis +| <- - punctuation +|^^^ - punctuation + + +http://spec.commonmark.org/0.27/#example-410 +foo *** +| ^^^ - punctuation + +http://spec.commonmark.org/0.27/#example-411 +foo *\** +| ^ punctuation.definition.italic.begin +| ^^ constant.character.escape +| ^ punctuation.definition.italic.end + +http://spec.commonmark.org/0.27/#example-412 +foo *_* +| ^ punctuation.definition.italic.begin +| ^ - punctuation +| ^ punctuation.definition.italic.end + +http://spec.commonmark.org/0.27/#example-414 +foo **\*** +| ^^ punctuation.definition.bold.begin +| ^^ constant.character.escape +| ^^ punctuation.definition.bold.end + +http://spec.commonmark.org/0.27/#example-415 +foo **_** +| ^^ punctuation.definition.bold.begin +| ^ - punctuation +| ^^ punctuation.definition.bold.end + +http://spec.commonmark.org/0.27/#example-422 +foo ___ +| ^^^^ - punctuation + +http://spec.commonmark.org/0.27/#example-423 +foo _\__ +| ^ punctuation.definition.italic.begin +| ^^ constant.character.escape +| ^ punctuation.definition.italic.end + +http://spec.commonmark.org/0.27/#example-424 +foo _*_ +| ^ punctuation.definition.italic.begin +| ^ - punctuation +| ^ punctuation.definition.italic.end + +http://spec.commonmark.org/0.27/#example-426 +foo __\___ +| ^^ punctuation.definition.bold.begin +| ^^ constant.character.escape +| ^^ punctuation.definition.bold.end + +http://spec.commonmark.org/0.27/#example-427 +foo __*__ +| ^^ punctuation.definition.bold.begin +| ^ - punctuation +| ^^ punctuation.definition.bold.end + +This text is _bold_, but this__text__is neither bold_nor_italic +| ^ punctuation.definition.italic +| ^^^^ markup.italic +| ^ punctuation.definition.italic +| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - markup.bold - markup.italic + +the following is italic *and doesn't end here * but does end here* +| ^ punctuation.definition.italic.begin +| ^ - punctuation.definition.italic +| ^ punctuation.definition.italic.end +the following is bold **and doesn't end here ** but does end here** +| ^^ punctuation.definition.bold.begin +| ^^ - punctuation.definition.bold +| ^^ punctuation.definition.bold.end +the following is not bold ** test **** +| ^^ - punctuation.definition.bold.begin +| ^^^^ - punctuation.definition.bold +the following is not italic _ test ____ +| ^ - punctuation.definition.italic.begin +| ^^^^ - punctuation.definition.italic + +more **tests *** ** here** +| ^^ punctuation.definition.bold.begin +| ^^^^^^ - punctuation.definition +| ^^ punctuation.definition.bold.end +more __tests *** ** example __ here__ +| ^^ punctuation.definition.bold.begin +| ^^^^^^^^^^^^^^^^^^^^^^ - punctuation.definition +| ^^ punctuation.definition.bold.end +more _tests here_ +| ^ punctuation.definition.italic.begin +| ^ - punctuation.definition +| ^ punctuation.definition.italic.end +more _tests _here_ +| ^ punctuation.definition.italic.begin +| ^ - punctuation.definition +| ^ - punctuation +| ^ punctuation.definition.italic.end +_more `tests_` here_ +| <- punctuation.definition.italic.begin +| ^^^^^^^^ markup.raw.inline +| ^ punctuation.definition.italic.end +__more `tests__` here__ +| <- punctuation.definition.bold.begin +| ^^^^^^^^^ markup.raw.inline +| ^^ punctuation.definition.bold.end +**more `tests__` here** +| <- punctuation.definition.bold.begin +| ^^^^^^^^^ markup.raw.inline +| ^^ punctuation.definition.bold.end +**more `tests**` here** +| <- punctuation.definition.bold.begin +| ^^^^^^^^^ markup.raw.inline +| ^^ punctuation.definition.bold.end +*more `tests__` here** +| <- punctuation.definition.italic.begin +| ^^ - punctuation +abc* +| ^ punctuation.definition.italic.end + +_test text_ foobar +| <- punctuation +| ^ punctuation.definition.italic.end +__test text__ not formatted +| <- punctuation +| ^^ punctuation.definition.bold.end +*test text* not formatted +| <- punctuation +| ^ punctuation.definition.italic.end +**test text** not formatted +| <- punctuation +| ^^ punctuation.definition.bold.end +_test text **formatted**_ +| <- punctuation +| ^^ punctuation +| ^^ punctuation +| ^ punctuation +*test text __formatted__* +| <- punctuation +| ^^ punctuation +| ^^ punctuation +| ^ punctuation +*test text __formatted__* **more** _text_ +| <- punctuation +| ^^ punctuation +| ^^ punctuation +| ^ punctuation +| ^^ punctuation +| ^^ punctuation +| ^ punctuation +| ^ punctuation +*test text* __formatted__ +| <- punctuation +| ^ punctuation +| ^^ punctuation +| ^^ punctuation + +__test text__ *formatted* +| <- punctuation +| ^^ punctuation +| ^ punctuation +| ^ punctuation + +This is ***bold italic*** +| ^^^^^^^^^^^^^^^^^ markup.bold +| ^^ punctuation.definition.bold.begin +| ^ punctuation.definition.italic.begin +| ^^^^^^^^^^^^^ markup.italic +| ^ punctuation.definition.italic.end +| ^^ punctuation.definition.bold.end + +This is ***bold italic* and just bold** +| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ markup.bold +| ^^ punctuation.definition.bold.begin +| ^ punctuation.definition.italic.begin +| ^^^^^^^^^^^^^ markup.italic +| ^ punctuation.definition.italic.end +| ^^^^^^^^^^^^^^^^ - markup.italic +| ^^ punctuation.definition.bold.end + +The next scope overlap funny because we have to pick one order +to scope three indicators in a row +This is ***bold italic** and just italic* +| ^^^^^^^^^^^^^^^^ markup.bold +| ^^ punctuation.definition.bold.begin +| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ markup.italic +| ^ punctuation.definition.italic.begin +| ^^ punctuation.definition.bold.end +| ^^^^^^^^^^^^^^^^^ - markup.bold +| ^ punctuation.definition.italic.end + +This is **_bold italic_** +| ^^^^^^^^^^^^^^^^^ markup.bold +| ^^ punctuation.definition.bold.begin +| ^ punctuation.definition.italic.begin +| ^^^^^^^^^^^^^ markup.italic +| ^ punctuation.definition.italic.end +| ^^ punctuation.definition.bold.end + +This is __*bold italic*__ +| ^^^^^^^^^^^^^^^^^ markup.bold +| ^^ punctuation.definition.bold.begin +| ^ punctuation.definition.italic.begin +| ^^^^^^^^^^^^^ markup.italic +| ^ punctuation.definition.italic.end +| ^^ punctuation.definition.bold.end + +This is ___bold italic___ +| ^^^^^^^^^^^^^^^^^ markup.bold +| ^^ punctuation.definition.bold.begin +| ^ punctuation.definition.italic.begin +| ^^^^^^^^^^^^^ markup.italic +| ^ punctuation.definition.italic.end +| ^^ punctuation.definition.bold.end + +This is ___bold italic_ and just bold__ +| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ markup.bold +| ^^ punctuation.definition.bold.begin +| ^ punctuation.definition.italic.begin +| ^^^^^^^^^^^^^ markup.italic +| ^ punctuation.definition.italic.end +| ^^^^^^^^^^^^^^^^ - markup.italic +| ^^ punctuation.definition.bold.end + +The next scope overlap funny because we have to pick one order +to scope three indicators in a row +This is ___bold italic__ and just italic_ +| ^^^^^^^^^^^^^^^ markup.bold +| ^^ punctuation.definition.bold.begin +| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ markup.italic +| ^ punctuation.definition.italic.begin +| ^^ punctuation.definition.bold.end +| ^^^^^^^^^^^^^^^^^ - markup.bold +| ^ punctuation.definition.italic.end + +This is _**italic bold**_ +| ^^^^^^^^^^^^^^^^^ markup.italic +| ^ punctuation.definition.italic.begin +| ^^^^^^^^^^^^^^^ markup.bold +| ^^ punctuation.definition.bold.begin +| ^^ punctuation.definition.bold.end +| ^ punctuation.definition.italic.end + +This is *__italic bold__* +| ^^^^^^^^^^^^^^^^^ markup.italic +| ^ punctuation.definition.italic.begin +| ^^^^^^^^^^^^^^^ markup.bold +| ^^ punctuation.definition.bold.begin +| ^^ punctuation.definition.bold.end +| ^ punctuation.definition.italic.end + +**test!_test** Issue 1163 +|^^^^^^^^^^^^^ markup.bold +| ^ - punctuation.definition.italic +| ^^ punctuation.definition.bold.end + +__test!*test__ Issue 1163 +|^^^^^^^^^^^^^ markup.bold +| ^ - punctuation.definition.italic +| ^^ punctuation.definition.bold.end + +# Strikethrough Tests + +__~~bold striked~~__ +| <- markup.bold.markdown punctuation.definition.bold.begin.markdown +|^ markup.bold.markdown - markup.strikethrough +| ^^^^^^^^^^^^^^^^ markup.bold.markdown markup.strikethrough.markdown-gfm +| ^^ markup.bold.markdown - markup.strikethrough +|^ punctuation.definition.bold.begin.markdown +| ^^ punctuation.definition.strikethrough.begin.markdown +| ^^ punctuation.definition.strikethrough.end.markdown +| ^^ punctuation.definition.bold.end.markdown + +**~~bold striked~~** +| <- markup.bold.markdown punctuation.definition.bold.begin.markdown +|^ markup.bold.markdown - markup.strikethrough +| ^^^^^^^^^^^^^^^^ markup.bold.markdown markup.strikethrough.markdown-gfm +| ^^ markup.bold.markdown - markup.strikethrough +|^ punctuation.definition.bold.begin.markdown +| ^^ punctuation.definition.strikethrough.begin.markdown +| ^^ punctuation.definition.strikethrough.end.markdown +| ^^ punctuation.definition.bold.end.markdown + +_~~italic striked~~_ +| <- markup.italic.markdown punctuation.definition.italic.begin.markdown +|^^^^^^^^^^^^^^^^^^ markup.italic.markdown markup.strikethrough.markdown-gfm +| ^ markup.italic.markdown - markup.strikethrough +|^^ punctuation.definition.strikethrough.begin.markdown +| ^^ punctuation.definition.strikethrough.end.markdown +| ^ punctuation.definition.italic.end.markdown + +*~~italic striked~~* +| <- markup.italic.markdown punctuation.definition.italic.begin.markdown +|^^^^^^^^^^^^^^^^^^ markup.italic.markdown markup.strikethrough.markdown-gfm +| ^ markup.italic.markdown - markup.strikethrough +|^^ punctuation.definition.strikethrough.begin.markdown +| ^^ punctuation.definition.strikethrough.end.markdown +| ^ punctuation.definition.italic.end.markdown + +___~~bold italic striked~~___ +| <- markup.bold.markdown punctuation.definition.bold.begin.markdown +|^ markup.bold.markdown - markup.italic - markup.strikethrough +| ^ markup.bold.markdown markup.italic.markdown - markup.strikethrough +| ^^^^^^^^^^^^^^^^^^^^^^^ markup.bold.markdown markup.italic.markdown markup.strikethrough.markdown-gfm +| ^ markup.bold.markdown markup.italic.markdown - markup.strikethrough +| ^^ markup.bold.markdown - markup.italic - markup.strikethrough +|^ punctuation.definition.bold.begin.markdown +| ^ punctuation.definition.italic.begin.markdown +| ^^ punctuation.definition.strikethrough.begin.markdown +| ^^ punctuation.definition.strikethrough.end.markdown +| ^ punctuation.definition.italic.end.markdown +| ^^ punctuation.definition.bold.end.markdown + +***~~bold italic striked~~*** +| <- markup.bold.markdown punctuation.definition.bold.begin.markdown +|^ markup.bold.markdown - markup.italic - markup.strikethrough +| ^ markup.bold.markdown markup.italic.markdown - markup.strikethrough +| ^^^^^^^^^^^^^^^^^^^^^^^ markup.bold.markdown markup.italic.markdown markup.strikethrough.markdown-gfm +| ^ markup.bold.markdown markup.italic.markdown - markup.strikethrough +| ^^ markup.bold.markdown - markup.italic - markup.strikethrough +|^ punctuation.definition.bold.begin.markdown +| ^ punctuation.definition.italic.begin.markdown +| ^^ punctuation.definition.strikethrough.begin.markdown +| ^^ punctuation.definition.strikethrough.end.markdown +| ^ punctuation.definition.italic.end.markdown +| ^^ punctuation.definition.bold.end.markdown + +~Hi~ Hello, world! +| <- punctuation.definition.strikethrough.begin +|^^^ meta.paragraph markup.strikethrough +| ^ punctuation.definition.strikethrough.end +| ^^^^^^^^^^^^^^^ meta.paragraph - markup + +This ~text~~~~ is ~~~~curious~. +| ^^^^^^^^^ meta.paragraph markup.strikethrough +| ^^^^^^^^^^^^ meta.paragraph markup.strikethrough +| ^^ meta.paragraph - markup +| ^ punctuation.definition.strikethrough.begin +| ^^^^ punctuation.definition.strikethrough.end +| ^^^^ punctuation.definition.strikethrough.begin +| ^ punctuation.definition.strikethrough.end + +This ~~has a +| ^^^^^^^^ meta.paragraph markup.strikethrough + +| <- meta.paragraph markup.strikethrough invalid.illegal.non-terminated.bold-italic +new paragraph~~. +| ^^ meta.paragraph markup.strikethrough punctuation.definition.strikethrough.begin + +| <- invalid.illegal.non-terminated.bold-italic + + +# Fenced Code Block Tests + +Paragraph is terminated by fenced code blocks. +``` +| <- meta.code-fence.definition.begin.text.markdown-gfm punctuation.definition.raw.code-fence.begin.markdown +``` +| <- meta.code-fence.definition.end.text.markdown-gfm punctuation.definition.raw.code-fence.end.markdown + +Code blocks terminate **bold text +``` +| <- meta.code-fence.definition.begin.text.markdown-gfm punctuation.definition.raw.code-fence.begin.markdown +``` +| <- meta.code-fence.definition.end.text.markdown-gfm punctuation.definition.raw.code-fence.end.markdown +this must not be bold** +| <- - meta.bold +|^^^^^^^^^^^^^^^^^^^^^^^ - meta.bold + +Code blocks terminate __bold text +``` +| <- meta.code-fence.definition.begin.text.markdown-gfm punctuation.definition.raw.code-fence.begin.markdown +``` +| <- meta.code-fence.definition.end.text.markdown-gfm punctuation.definition.raw.code-fence.end.markdown +this must not be bold__ +| <- - meta.bold +|^^^^^^^^^^^^^^^^^^^^^^^ - meta.bold + +Code blocks terminate *italic text +``` +| <- meta.code-fence.definition.begin.text.markdown-gfm punctuation.definition.raw.code-fence.begin.markdown +``` +| <- meta.code-fence.definition.end.text.markdown-gfm punctuation.definition.raw.code-fence.end.markdown +this must not be italic* +| <- - meta.italic +|^^^^^^^^^^^^^^^^^^^^^^^ - meta.italic + +Code blocks terminate _italic text +``` +| <- meta.code-fence.definition.begin.text.markdown-gfm punctuation.definition.raw.code-fence.begin.markdown +``` +| <- meta.code-fence.definition.end.text.markdown-gfm punctuation.definition.raw.code-fence.end.markdown +this must not be italic_ +| <- - meta.italic +|^^^^^^^^^^^^^^^^^^^^^^^ - meta.bold - meta.italic + +Code blocks terminate ***bold italic text +``` +| <- meta.code-fence.definition.begin.text.markdown-gfm punctuation.definition.raw.code-fence.begin.markdown +``` +| <- meta.code-fence.definition.end.text.markdown-gfm punctuation.definition.raw.code-fence.end.markdown +this must not be bold italic*** +| <- - meta.bold - meta.italic +|^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - meta.bold - meta.italic + +Code blocks terminate ___bold italic text +``` +| <- meta.code-fence.definition.begin.text.markdown-gfm punctuation.definition.raw.code-fence.begin.markdown +``` +| <- meta.code-fence.definition.end.text.markdown-gfm punctuation.definition.raw.code-fence.end.markdown +this must not be bold italic___ +| <- - meta.bold - meta.italic +|^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - meta.bold - meta.italic + +Code blocks terminate **_bold italic text +``` +| <- meta.code-fence.definition.begin.text.markdown-gfm punctuation.definition.raw.code-fence.begin.markdown +``` +| <- meta.code-fence.definition.end.text.markdown-gfm punctuation.definition.raw.code-fence.end.markdown +this must not be bold italic_** +| <- - meta.bold - meta.italic +|^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - meta.bold - meta.italic + +```js +| <- punctuation.definition.raw.code-fence.begin +| ^^ constant.other.language-name +for (var i = 0; i < 10; i++) { +| ^ source.js keyword.control.loop + console.log(i); +} +``` +| <- punctuation.definition.raw.code-fence.end + +```ts +| ^^ constant.other.language-name +declare type foo = 'bar' +``` + +```R%&?! weired language name +|^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ meta.code-fence.definition.begin.text.markdown-gfm +| ^^^^^ constant.other.language-name.markdown +| ^^^^^^^^^^^^^^^^^^^^^ - constant +``` + +```{key: value} +|^^^^^^^^^^^^^^^ meta.code-fence.definition.begin.text.markdown-gfm +| ^^^^^^^^^^^^ - constant +``` + +``` {key: value} +|^^^^^^^^^^^^^^^^ meta.code-fence.definition.begin.text.markdown-gfm +| ^^^^^^^^^^^^ - constant +``` + +```testing``123``` +| <- punctuation.definition.raw.begin +| ^^ - punctuation +| ^^^ punctuation.definition.raw.end +```testing``123```` +| <- punctuation.definition.raw.begin +| ^ - punctuation +| ^^^^ - punctuation +``` +| <- punctuation.definition.raw.end +``testing`123```` +| <- punctuation.definition.raw.begin +| ^ - punctuation +| ^^^^ - punctuation +more text`` +| ^^ punctuation.definition.raw.end +``text + +| <- invalid.illegal.non-terminated.raw +text +| <- - markup.raw + +http://spec.commonmark.org/0.28/#example-315 +`` foo ` bar `` +|^ punctuation.definition.raw.begin +|^^^^^^^^^^^^^^^ markup.raw.inline +| ^ - punctuation +| ^^ punctuation.definition.raw.end + +http://spec.commonmark.org/0.28/#example-316 +` `` ` +|<- punctuation.definition.raw.begin +|^^^^^ markup.raw.inline +| ^^ - punctuation +| ^ punctuation.definition.raw.end + +http://spec.commonmark.org/0.28/#example-318 +`foo bar + baz` +|^^^^^ markup.raw.inline +| ^ punctuation.definition.raw.end + +~~~~ +| <- punctuation.definition.raw.code-fence.begin + ~~~~ +| ^^^ punctuation.definition.raw.code-fence.end + +~~~~~test~ +| ^^^^^^^^^ meta.paragraph - constant - markup.raw + +~~~~~~test +| ^^^^ punctuation.definition.raw.code-fence.begin +| ^^^^ constant.other.language-name +~~~~~~ +| ^^^^ punctuation.definition.raw.code-fence.end + +```test +| ^^^^ constant.other.language-name + ``` +| ^^^ punctuation.definition.raw.code-fence.end + +hello world ````test```` +| ^^^^^^^^^^^^ markup.raw.inline +| ^ - markup.raw + +`foo `` bar` +| ^^^^^^ markup.raw.inline - punctuation +| ^ punctuation.definition.raw.end + +hard line break +| ^^ meta.hard-line-break punctuation.definition.hard-line-break +hard line break\ +| ^ meta.hard-line-break constant.character.escape +hard line break +| ^^^^^ meta.hard-line-break punctuation.definition.hard-line-break +soft line break +| ^^ - meta.hard-line-break +soft line break +| ^^ - meta.hard-line-break + +### foo +| ^^^ - meta.hard-line-break +### foo\ +| ^ - meta.hard-line-break + +`inline code with trailing spaces +| ^^^ - meta.hard-line-break +not a hard line break` + +*test + +| <- invalid.illegal.non-terminated.bold-italic +abc* +| ^ - punctuation + +_test + +| <- invalid.illegal.non-terminated.bold-italic +abc_ +| ^ - punctuation + +**test + +| <- invalid.illegal.non-terminated.bold-italic +abc** +| ^^ - punctuation + +__test + +| <- invalid.illegal.non-terminated.bold-italic +abc__ +| ^^ - punctuation + +__test\ +| ^ meta.hard-line-break constant.character.escape +testing__ + +- test *testing +blah* +| ^ markup.list.unnumbered meta.paragraph.list markup.italic punctuation.definition.italic.end - meta.paragraph.list meta.paragraph.list +- fgh +- *ghgh +| ^ markup.list.unnumbered meta.paragraph.list markup.italic punctuation.definition.italic.begin - meta.paragraph.list meta.paragraph.list +- fgfg +| <- markup.list.unnumbered.bullet punctuation.definition.list_item +- _test + +| <- markup.list.unnumbered meta.paragraph.list markup.italic invalid.illegal.non-terminated.bold-italic + still a list item +| ^^^^^^^^^^^^^^^^^^ markup.list.unnumbered meta.paragraph.list +- * * * * * * * +| <- punctuation.definition.list_item +| ^^^^^^^^ markup.list.unnumbered meta.paragraph.list meta.separator.thematic-break - meta.paragraph.list meta.paragraph.list +| ^ punctuation.definition.thematic-break +| ^ punctuation.definition.thematic-break +| ^ punctuation.definition.thematic-break +| ^ punctuation.definition.thematic-break +| ^ punctuation.definition.thematic-break +| ^ punctuation.definition.thematic-break +| ^ punctuation.definition.thematic-break +| ^ - punctuation.definition.thematic-break +| ^ - punctuation.definition.thematic-break +| ^ - punctuation.definition.thematic-break +| ^ - punctuation.definition.thematic-break +| ^ - punctuation.definition.thematic-break +| ^ - punctuation.definition.thematic-break + still a list item +| ^^^^^^^^^^^^^^^^^^ markup.list.unnumbered meta.paragraph.list - meta.paragraph.list meta.paragraph.list + +http://spec.commonmark.org/0.27/#example-407 +**foo [*bar*](/url)** +| <- punctuation.definition.bold.begin +| ^^^^^^^^^^^^^ markup.bold meta.link.inline +| ^^ punctuation.definition.bold.end +| ^ punctuation.definition.italic.begin +| ^ punctuation.definition.italic.end +**foo [_bar_](/url)** +| <- punctuation.definition.bold.begin +| ^^^^^^^^^^^^^ markup.bold meta.link.inline +| ^^ punctuation.definition.bold.end +| ^ punctuation.definition.italic.begin +| ^ punctuation.definition.italic.end +_foo [**bar**](/url)_ +| <- punctuation.definition.italic.begin +| ^^^^^^^^^^^^^^^ markup.italic meta.link.inline +| ^ punctuation.definition.italic.end +| ^^ punctuation.definition.bold.begin +| ^^ punctuation.definition.bold.end + + +1. Open `Command Palette` using menu item `Tools → Command Palette...` +|^ markup.list.numbered punctuation.definition.list_item +| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ markup.list.numbered meta.paragraph.list markup.raw.inline +2. Choose `Package Control: Install Package` + +[**Read more →**][details] +|^^ punctuation.definition.bold.begin +| ^^^^^^^ constant.character.entity.decimal.html +| ^^ punctuation.definition.bold.end +| ^^^^^^^ constant.other.reference.link + +[Read more →][details] +| ^^^^^^^ constant.character.entity.decimal.html +| ^^^^^^^ constant.other.reference.link + +[Read more ][details] +|^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ meta.link.reference.description +| ^^^^^^^^^^^^^^^^^^ source.css +| ^^^^^^^ constant.character.entity.decimal.html +| ^^^^^^^ constant.other.reference.link + +[![Cool ★ Image - Click to Enlarge][img-example]][img-example] +|^ punctuation.definition.image.begin +| ^^^^^^^^^^^ constant.other.reference.link +| ^ punctuation.definition.link.end +| ^^^^^^^^^^^ constant.other.reference.link + +[![Cool ★ Image - Click to Enlarge](http://www.sublimetext.com/anim/rename2_packed.png)](http://www.sublimetext.com/anim/rename2_packed.png) +|^ punctuation.definition.image.begin +| ^ punctuation.definition.metadata.begin +| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ markup.underline.link.image +| ^ punctuation.definition.metadata.end +| ^ punctuation.definition.metadata.begin +| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ markup.underline.link +| ^ punctuation.definition.metadata.end + +[img-example]: http://www.sublimetext.com/anim/rename2_packed.png +|^^^^^^^^^^^ meta.link.reference.def entity.name.reference.link +| ^ punctuation.separator.key-value +| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ markup.underline.link +| ^ - meta.link - markup + +[//]: # (This is a comment without a line-break.) +| ^ meta.link.reference.def markup.underline.link +| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ string.other.link.description.title +| ^ - meta.link + +[//]: # (This is a comment with a +| ^ meta.link.reference.def markup.underline.link +| ^ punctuation.definition.string.begin + line-break.) +| ^ punctuation.definition.string.end +| ^ - meta.link + +[//]: # (testing)blah +|^^^^^^^^^^^^^^^^^^^^ meta.link.reference.def.markdown +| ^ punctuation.definition.string.begin +| ^ punctuation.definition.string.end +| ^^^^ invalid.illegal.expected-eol +| ^ - meta.link - invalid + +[//]: # (testing +blah +| <- meta.link.reference.def string.other.link.description.title + +| <- invalid.illegal.non-terminated.link-title +text +| <- meta.paragraph - meta.link.reference.def + +[foo]: "test" +|^^^^^^^^^^^^^^^^^^^ meta.link.reference.def.markdown +| ^ - meta.link +| ^ punctuation.definition.link.begin +| ^^^ markup.underline.link +| ^ punctuation.definition.link.end +| ^^^^^^ string.other.link.description.title +| ^ - invalid.illegal.expected-eol + +[foo]: > "test" +|^^^^^^^^^^^^^^^^^^^^ meta.link.reference.def.markdown +| ^ - meta.link +| ^ punctuation.definition.link.begin +| ^^^ markup.underline.link +| ^ punctuation.definition.link.end +| ^^^^^^^^ invalid.illegal.expected-eol +| ^ - invalid.illegal.expected-eol + +https://michelf.ca/projects/php-markdown/extra/#footnotes +That's some text with a footnote.[^1] +| ^^^^ meta.paragraph meta.link.reference.footnote.markdown-extra +| ^^ punctuation.definition.link.begin +| ^ meta.link.reference.literal.footnote-id +| ^ punctuation.definition.link.end + + [^1]: And that's the footnote. +|^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ meta.link.reference.def.footnote.markdown-extra +|^ punctuation.definition.constant.begin +| ^ punctuation.definition.constant.end +| ^^ entity.name.reference.link +| ^ punctuation.separator.key-value + +[^1]: + And that's the footnote. + + That's the *second* paragraph. +|^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ meta.link.reference.def.footnote.markdown-extra - markup.raw +| ^^^^^^^^ markup.italic + +- a + - b + - c + - d +| ^ markup.list.unnumbered.bullet punctuation.definition.list_item + text here +| ^^^^^^^^^^ markup.list.unnumbered meta.paragraph.list - markup.raw.block - meta.paragraph.list meta.paragraph.list + + code here + | ^^^^^^^^ markup.raw.block + + - e +| ^ markup.list.unnumbered.bullet punctuation.definition.list_item + + code here + + > block quote code here +| ^ markup.list.unnumbered markup.quote punctuation.definition.blockquote +| ^^^^^^^^^^^^^^^^^^^^^^ markup.list.unnumbered markup.quote markup.raw.block + + > > test +| ^ markup.list.unnumbered markup.quote punctuation.definition.blockquote +| ^ markup.list.unnumbered markup.quote markup.quote punctuation.definition.blockquote - markup.raw.block + + - f +| ^ markup.list.unnumbered.bullet punctuation.definition.list_item + 1. test +| ^^ markup.list.numbered.bullet +| ^ punctuation.definition.list_item + +abc +| <- meta.paragraph - markup.list + +| foo | bar | +|^^^^^^^^^^^^^ meta.block-level meta.table.header +| <- punctuation.separator.table-cell +| ^ punctuation.separator.table-cell +| ^ punctuation.separator.table-cell +| ^^^^ - punctuation.separator.table-cell +| --- | --- | +| baz | bim Ctrl+C | +| <- meta.block-level meta.table punctuation.separator.table-cell +| ^^^^^ meta.tag.inline.any +| ^ punctuation.separator.table-cell + +| <- - meta.block-level - meta.table + +| abc | defghi | +:-: | -----------: +|^^^^^^^^^^^^^^^^^ meta.block-level meta.table.header-separator +| <- punctuation.definition.table-cell-alignment +|^ punctuation.section.table-header +| ^ punctuation.separator.table-cell +| ^^^^^^^^^^^ punctuation.section.table-header +| ^ punctuation.definition.table-cell-alignment - punctuation.section.table-header +bar | baz +| ^ meta.block-level meta.table punctuation.separator.table-cell + +| f\|oo | +| <- meta.block-level meta.table punctuation.separator.table-cell +| ^^ meta.block-level meta.table constant.character.escape - punctuation.separator.table-cell +| ^ meta.block-level meta.table punctuation.separator.table-cell +| ------ | +| b `|` az | +| ^^^ meta.block-level meta.table markup.raw.inline - meta.table.header-separator +| ^ meta.block-level meta.table punctuation.separator.table-cell +| b **|** im | +| <- meta.block-level meta.table punctuation.separator.table-cell +| ^^^^^ meta.block-level meta.table markup.bold - punctuation.separator.table-cell +| ^ meta.block-level meta.table punctuation.separator.table-cell + +| abc | def | +| --- | --- | +| bar | baz | +|^^^^^^^^^^^^^ meta.block-level meta.table +test +|^^^^ meta.block-level meta.table +> bar +| <- meta.block-level markup.quote punctuation.definition.blockquote - meta.table + +`|` this `|` example `|` is not a table `|` +| ^ punctuation.definition.raw.end - meta.table +| nor is this | because it is not at block level, it immediately follows a paragraph | +| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ meta.paragraph - meta.table + +| First Header | Second Header | Third Header | +| :------------ | :-----------: | -------------------: | +| First row | Data | Very long data entry | +| Second row | **Cell** | *Cell* | +| Third row | Cell that spans across two columns || +| ^^^^^^^^^^^^^^ meta.block-level meta.table +| ^^ punctuation.separator.table-cell + + | table that doesn't start at column 0 | + | ---- | + | blah | +| ^^^^^^^^ meta.table +| ^ punctuation.separator.table-cell + +not a table | +| ^^^^^^^^^^^^^ - meta.table + + abc | def + --- | --- + --- | --- +| ^^^^ meta.block-level meta.table - meta.table.header + + a | b + - | - +|^^^^^^ meta.block-level.markdown meta.table.header-separator.markdown-gfm +|^ punctuation.section.table-header.markdown +| ^ punctuation.separator.table-cell.markdown +| ^ punctuation.section.table-header.markdown + - | - +|^^^^^^ meta.block-level.markdown meta.table.markdown-gfm + + a | b + -:| - +|^^^^^^ meta.block-level.markdown meta.table.header-separator.markdown-gfm +|^ punctuation.section.table-header.markdown +| ^ punctuation.definition.table-cell-alignment.markdown +| ^ punctuation.separator.table-cell.markdown +| ^ punctuation.section.table-header.markdown + - | - +|^^^^^^ meta.block-level.markdown meta.table.markdown-gfm + +| test | me | +|------|----| +|^^^^^^ punctuation.section.table-header +|*test | me | +|^^^^^^ - markup.bold +| ^ punctuation.separator.table-cell +| ^ punctuation.separator.table-cell +|`test | me | +|^ invalid.deprecated.unescaped-backticks +| ^ punctuation.separator.table-cell + +A line without bolded | +| ^ - punctuation.separator.table-cell + +A line with bolded **|** +| ^ - punctuation.separator.table-cell + +1. test +| ^^^^^ markup.list.numbered meta.paragraph.list + - test +|^^^^^^^^^ markup.list.unnumbered +| ^ markup.list.unnumbered.bullet punctuation.definition.list_item +| ^^^^^ meta.paragraph.list + - test +|^^^^^^^^^ markup.list.unnumbered +| ^ markup.list.unnumbered.bullet punctuation.definition.list_item +| ^^^^^ meta.paragraph.list + test +|^^^^^^^ markup.list.numbered meta.paragraph.list + ****test**** +|^^^^^^^^^^^^^ markup.list.numbered meta.paragraph.list - punctuation + + - - test +|^ punctuation.definition.list_item +| ^^^^^^^ markup.list.unnumbered meta.paragraph.list - punctuation +- - - - test +| <- punctuation.definition.list_item +| ^^^^^^^^^^^ markup.list.unnumbered meta.paragraph.list - punctuation + +paragraph + + * List Item 1 + Text under Item 1 + * List Item 2 + Text under Item 2 + + * List Item 3 + Text under Item 3 +| ^^^^^^^^^^^^^^^^^^ markup.list.unnumbered meta.paragraph.list - markup.raw + + 1. fenced code block inside a list item +| ^ punctuation.definition.list_item + ```language +|^^^^^^^^^^^^^^^ meta.paragraph.list +| ^^^ punctuation.definition.raw.code-fence.begin +| ^^^^^^^^ constant.other.language-name +| ^^^^^^^^^^^ meta.code-fence + +|^^^^ meta.paragraph.list markup.raw.code-fence + ``` +| ^^^ punctuation.definition.raw.code-fence.end + test +| ^^^^^ meta.paragraph.list - markup.raw.code-fence + + 2. test +| ^ punctuation.definition.list_item + +Normal paragraph +| <- meta.paragraph - markup + +1. List + 1. Nested list + 2. Second item + + This line is still list item 1 +|^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ markup.list.numbered - markup.raw.block + +Test +| <- meta.paragraph - markup.list + +http://spec.commonmark.org/0.28/#example-116 + +
+
+**Hello**,
+| ^^^^^^^^^ meta.disable-markdown
+
+_world_.
+| ^^^^ markup.italic - meta.disable-markdown
+
+
+ +http://spec.commonmark.org/0.28/#example-120 + +
+| ^^^^^^^^^^^^^^^^ meta.disable-markdown + +*Markdown* +| ^^^^^^^ meta.paragraph markup.italic - meta.disable-markdown + +
+| ^^^ meta.disable-markdown meta.tag.block.any.html + +http://spec.commonmark.org/0.28/#example-127 + +
+| ^^^^^ meta.disable-markdown - markup.italic + +http://spec.commonmark.org/0.28/#example-129 + +
+``` c +int x = 33; +``` +| ^^ meta.disable-markdown + +http://spec.commonmark.org/0.28/#example-130 + + +*bar* +|^^^^^ meta.disable-markdown + + +http://spec.commonmark.org/0.28/#example-131 + + +*bar* +|^^^^^ meta.disable-markdown + +| ^^^^^^^ meta.disable-markdown meta.tag.other.html entity.name.tag.other.html + +http://spec.commonmark.org/0.28/#example-135 + + +| ^^ meta.disable-markdown meta.tag.inline.any.html entity.name.tag.inline.any.html + +*foo* +| ^^ meta.paragraph markup.italic + + +| ^^^ meta.disable-markdown meta.tag.inline.any.html entity.name.tag.inline.any.html + + +*foo* +|^^^^^ meta.disable-markdown + + +http://spec.commonmark.org/0.28/#example-136 + +*foo* +| ^^ meta.tag.inline.any.html entity.name.tag.inline.any.html +| ^^^^^ markup.italic +| ^^^ meta.tag.inline.any.html entity.name.tag.inline.any.html +|^^^^^^^^^^^^^^^ meta.paragraph - meta.disable-markdown + +http://spec.commonmark.org/0.28/#example-137 + +

+| ^^ meta.disable-markdown meta.tag.block.any.html entity.name.tag.block.any.html
+import Text.HTML.TagSoup
+
+main :: IO ()
+| ^^^^^^^^^^^^ meta.disable-markdown
+main = print $ parseTags tags
+
+| ^^^^^^^^^^^ meta.disable-markdown +| ^^^ meta.tag.block.any.html entity.name.tag.block.any.html +okay +| <- - meta.disable-markdown + +http://spec.commonmark.org/0.28/#example-138 + + +| ^^^^^^ meta.disable-markdown meta.tag.script.end.html entity.name.tag.script.html +okay +| <- - meta.disable-markdown + +http://spec.commonmark.org/0.28/#example-139 + + +| ^^^^^ meta.disable-markdown meta.tag.style.end.html entity.name.tag.style.html +okay +| <- - meta.disable-markdown + +http://spec.commonmark.org/0.28/#example-143 + + +| ^^^^^^^^^^^^^^^^^^^^^^^^^^^ meta.disable-markdown +*foo* +| <- - meta.disable-markdown + +http://spec.commonmark.org/0.28/#example-144 + +*bar* +| ^^^^^^^^^^ comment.block.html +| ^^^^^ meta.disable-markdown +*baz* +| <- - meta.disable-markdown + +http://spec.commonmark.org/0.28/#example-145 + +1. *bar* +| ^^^^^^^^^^^^^^^^ meta.disable-markdown +okay +| <- - meta.disable-markdown + +http://spec.commonmark.org/0.28/#example-146 + + +| ^^^^^^^^ meta.disable-markdown comment.block.html +okay +| <- - meta.disable-markdown + +http://spec.commonmark.org/0.28/#example-147 + +'; + +?> +|^^ meta.disable-markdown +okay +| <- - meta.disable-markdown + +http://spec.commonmark.org/0.28/#example-148 + + +| ^^^^^^^ meta.disable-markdown meta.tag.sgml.doctype.html +okay +| <- - meta.disable-markdown + +http://spec.commonmark.org/0.28/#example-149 + + +|^ meta.disable-markdown meta.tag.sgml +okay +| <- - meta.disable-markdown + +1. Test + + ```python +| ^^^ markup.list.numbered meta.code-fence punctuation.definition.raw.code-fence.begin + Test + +| <- - invalid + Test + ``` +| ^^^ punctuation.definition.raw.code-fence.end + +1. Test 2 +|^ markup.list.numbered.bullet punctuation.definition.list_item + +```clojure +|^^^^^^^^^ meta.code-fence.definition.begin.clojure +| ^^^^^^^ constant.other.language-name + (/ 10 3.0) +|<- source.clojure +|^^^^^^^^^^ source.clojure +``` +|^^ meta.code-fence.definition.end.clojure punctuation.definition.raw.code-fence.end + +```diff ++ inserted +| <- source.diff markup.inserted.diff punctuation.definition.inserted.diff +- deleted +| <- source.diff markup.deleted.diff punctuation.definition.deleted.diff +``` + +```haskell + +| <- markup.raw.code-fence.haskell.markdown-gfm source.haskell +``` + +```html + +| <- markup.raw.code-fence.html.markdown-gfm text.html +| ^^^^^^ text.html meta.tag +``` + +```jsx + +| <- markup.raw.code-fence.jsx.markdown-gfm +``` + +```lisp + +| <- markup.raw.code-fence.lisp.markdown-gfm source.lisp +``` + +```lua + +| <- markup.raw.code-fence.lua.markdown-gfm source.lua +``` + +```matlab + +| <- markup.raw.code-fence.matlab.markdown-gfm source.matlab +``` + +```ocaml + +| <- markup.raw.code-fence.ocaml.markdown-gfm source.ocaml +``` + +```scala + +| <- markup.raw.code-fence.scala.markdown-gfm source.scala +``` + +```sh + +| <- markup.raw.code-fence.shell-script.markdown-gfm source.shell.bash +``` + +```shell + +| <- markup.raw.code-fence.shell-script.markdown-gfm source.shell.bash +``` + +```shell-script + +| <- markup.raw.code-fence.shell-script.markdown-gfm source.shell.bash +``` + +```tsx + +| <- markup.raw.code-fence.tsx.markdown-gfm +``` + +```xml +|^^^^^ meta.code-fence.definition.begin.xml +| ^^^ constant.other.language-name + +|^^^^^^^^^^^^^^^^^^^^^^ markup.raw.code-fence.xml +| ^^^^^^^ meta.tag.preprocessor.xml entity.other.attribute-name.localname.xml + + + +``` +|^^ punctuation.definition.raw.code-fence.end + +```sql +|^^^^^ meta.code-fence.definition.begin.sql +| ^^^ constant.other.language-name +SELECT TOP 10 * +|^^^^^^^^^^^^^^^ markup.raw.code-fence.sql +|^^^^^^^^^ keyword.other.DML.sql +FROM TableName +``` +|^^ meta.code-fence.definition.end.sql punctuation.definition.raw.code-fence.end - markup + +```python +|^^ punctuation.definition.raw.code-fence.begin +|^^^^^^^^^ meta.code-fence.definition.begin.python - markup +| ^^^^^^ constant.other.language-name +def function(): + pass +| ^^^^ keyword.control.flow +unclosed_paren = ( +| ^ meta.group.python punctuation.section.group.begin.python +``` +|^^ meta.code-fence.definition.end.python punctuation.definition.raw.code-fence.end + +```Graphviz +graph n {} +| ^^^ storage.type.dot +``` + +| <- - markup.raw + +```php +var_dump(expression); +| ^^^^^^ support.function.var.php +``` + +```html+php +
+|^^^ entity.name.tag.block.any.html += => <=> // && == != +| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - constant - keyword - variable + + -= += /= %= -- ++ ** !~ =~ ~~ <= >= => <=> // && == != +| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ meta.block-level markup.raw - constant - keyword - variable - punctuation + +> -= += /= %= -- ++ ** !~ =~ ~~ <= >= => <=> // && == != +| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ meta.block-level - constant - keyword - variable + +> > -= += /= %= -- ++ ** !~ =~ ~~ <= >= => <=> // && == != +| ^ meta.block-level.markdown markup.quote.markdown markup.quote.markdown punctuation.definition.blockquote.markdown +| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ meta.block-level - constant - keyword - variable + +\
+|<- constant.character.escape +|^ constant.character.escape +|^^^^^^ - meta.tag + +\ +|^ constant.character.escape +|^^^^^^ - meta.tag +| ^^ constant.character.escape + +link with a single underscore inside the text : [@_test](http://example.com) +| ^^^^^^ meta.paragraph meta.link.inline.description - punctuation.definition +| ^ meta.paragraph meta.link.inline punctuation.definition.link.end + +# h1 +- list +## h2 +|^ punctuation.definition.heading.begin +1. list +### h3 +|^^ punctuation.definition.heading.begin + +1. list [001]blah +| ^^^^^ meta.link.reference +| ^ punctuation.definition.link.begin +| ^ punctuation.definition.link.end +| ^^^^^ - meta.link + + [001]: https://en.wikipedia.org/wiki/Root-mean-square_deviation "Wikipedia - RMSE" +| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ markup.list.numbered meta.link.reference.def +1. another list item + +[foo]: /url "title" +|^^^^^^^^^^^^^^^^^^ meta.link.reference.def +| ^ punctuation.separator.key-value +| ^^^^ markup.underline.link +| ^^^^^^^ string.other.link.description.title + +[foo] +|<- meta.link.reference punctuation.definition.link.begin +|^^^ meta.paragraph meta.link.reference +| ^ meta.link.reference punctuation.definition.link.end + + [Foo*bar\]]:my_(url) 'title (with parens)' +|^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ meta.link.reference.def +|^ punctuation.definition.constant.begin +| ^^^^^^^^^ entity.name.reference.link - punctuation +| ^ punctuation.definition.constant.end +| ^ punctuation.separator.key-value +| ^^^^^^^^ markup.underline.link +| ^^^^^^^^^^^^^^^^^^^^^ string.other.link.description.title + + [foo]: <> +|^^^^^^^^^ meta.link.reference.def +| ^ punctuation.separator.key-value +| ^ punctuation.definition.link.begin +| ^ punctuation.definition.link.end + +# CriticMarkup ################################################################ + +This is an {++additional++} word in {++**bold**++}. +| ^^^^^^^^^^^^^^^^ markup.critic.addition.markdown +| ^^^ punctuation.definition.critic.begin.markdown - markup.inserted +| ^^^^^^^^^^ markup.inserted.critic.markdown +| ^^^ punctuation.definition.critic.end.markdown - markup.inserted +| ^^^ markup.critic.addition.markdown - markup.inserted - markup.bold +| ^^^^^^^^ markup.critic.addition.markdown markup.inserted.critic.markdown markup.bold.markdown +| ^^^ markup.critic.addition.markdown - markup.inserted +| ^^^ punctuation.definition.critic.begin.markdown +| ^^ punctuation.definition.bold.begin.markdown +| ^^ punctuation.definition.bold.end.markdown +| ^^^ punctuation.definition.critic.end.markdown + +This is an {++ multiline +addition ++} test. +| <- markup.critic.addition.markdown +|^^^^^^^^ markup.critic.addition.markdown markup.inserted.critic.markdown +| ^^^ markup.critic.addition.markdown - markup.inserted +| ^^^ punctuation.definition.critic.end.markdown +| ^^^^^^ - markup.critic + +Additional {++[Link](https://foo.bar)++} and {++![Image](images/image.png)++}. +| ^^^^^^^^^ - markup.critic +| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ markup.critic.addition.markdown +| ^^^^ - markup.critic +| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ markup.critic.addition.markdown +| ^^ - markup.critic +| ^^^ punctuation.definition.critic.begin.markdown +| ^ meta.link.inline.markdown punctuation.definition.link.begin.markdown +| ^^^^ meta.link.inline.description.markdown +| ^ meta.link.inline.markdown punctuation.definition.link.end.markdown +| ^^^^^^^^^^^^^^^^^ meta.link.inline.markdown +| ^^^ punctuation.definition.critic.end.markdown +| ^^^ punctuation.definition.critic.begin.markdown +| ^^ meta.image.inline.markdown punctuation.definition.image.begin.markdown +| ^^^^^ meta.image.inline.description.markdown +| ^ meta.image.inline.markdown punctuation.definition.image.end.markdown +| ^^^^^^^^^^^^^^^^^^ meta.image.inline.markdown +| ^^^ punctuation.definition.critic.end.markdown + +This is a {-- deletion --} and {~~substitute~>with~~striked~~text~~} or {~~~~old~~~>~~new~~~~}. +| ^^^^^^^^^^^^^^^^ markup.critic.deletion.markdown +| ^^^ punctuation.definition.critic.begin.markdown - markup.deleted +| ^^^^^^^^^^ markup.deleted.critic.markdown +| ^^^ punctuation.definition.critic.end.markdown - markup.deleted +| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ markup.critic.substitution.markdown +| ^^^ - markup.critic +| ^^^^^^^^^^^^^^^^^^^^^^ markup.critic.substitution.markdown +| ^^ - markup.critic +| ^^^ punctuation.definition.critic.begin.markdown - markup.deleted +| ^^^^^^^^^^ markup.deleted.critic.markdown +| ^^ punctuation.separator.critic.markdown - markup.deleted - markup.inserted +| ^^^^^^^^^^^^^^^^^^ markup.inserted.critic.markdown +| ^^^^^^^^^^ markup.strikethrough.markdown-gfm +| ^^^ punctuation.definition.critic.end.markdown - markup.inserted +| ^^^ punctuation.definition.critic.begin.markdown +| ^^ punctuation.definition.strikethrough.begin.markdown +| ^^^^^^^ markup.deleted.critic.markdown markup.strikethrough.markdown-gfm +| ^^ punctuation.definition.strikethrough.end.markdown +| ^^ punctuation.separator.critic.markdown +| ^^ punctuation.definition.strikethrough.begin.markdown +| ^^^^^^^ markup.inserted.critic.markdown markup.strikethrough.markdown-gfm +| ^^ punctuation.definition.strikethrough.end.markdown +| ^^^ punctuation.definition.critic.end.markdown + + +This is a {>> comment <<}. +| ^^^^^^^^^^^^^^^ markup.critic.comment.markdown +| ^^^ punctuation.definition.critic.begin.markdown - comment +| ^^^^^^^^^ comment.critic.markdown +| ^^^ punctuation.definition.critic.end.markdown - comment +| ^ - markup.critic + +This is an {== information ==}{>> comment <<}. +| ^^^^^^^^^^^^^^^^^^^ markup.critic.highlight.markdown +| ^^^^^^^^^^^^^^^ markup.critic.comment.markdown +| ^^^ punctuation.definition.critic.begin.markdown - markup.info +| ^^^^^^^^^^^^^ markup.info.critic.markdown +| ^^^ punctuation.definition.critic.end.markdown - markup.info +| ^^^ punctuation.definition.critic.begin.markdown - comment +| ^^^^^^^^^ comment.critic.markdown +| ^^^ punctuation.definition.critic.end.markdown - comment +| ^^ - markup.critic + +This is a [[wiki link]]. +| ^^ meta.link.reference.wiki.markdown punctuation.definition.link.begin.markdown +| ^^^^^^^^^ meta.link.reference.wiki.description.markdown - punctuation +| ^^ meta.link.reference.wiki.markdown punctuation.definition.link.end.markdown \ No newline at end of file diff --git a/tests/syntax_test_multimarkdown.md b/tests/syntax_test_multimarkdown.md new file mode 100644 index 00000000..f654877d --- /dev/null +++ b/tests/syntax_test_multimarkdown.md @@ -0,0 +1,36 @@ +T: SYNTAX TEST "Packages/MarkdownEditing/syntaxes/MultiMarkdown.sublime-syntax" +Title: A Sample MultiMarkdown Document +T: ^^ meta.header.multimarkdown keyword.other.multimarkdown +T: ^ meta.header.multimarkdown punctuation.separator.key-value.multimarkdown +T: ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ meta.header.multimarkdown string.unquoted.multimarkdown +T: ^ meta.header.multimarkdown - string +Author: Fletcher T. Penney +T:^^^^ meta.header.multimarkdown keyword.other.multimarkdown +T: ^ meta.header.multimarkdown punctuation.separator.key-value.multimarkdown +T: ^^^^^^^^^^^^^^^^^^ meta.header.multimarkdown string.unquoted.multimarkdown +Date: February 9, 2011 +Comment: This is a comment intended to demonstrate + metadata that spans multiple lines, yet + is treated as a single value. +T: ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ meta.header.multimarkdown string.unquoted.multimarkdown +T: ^ meta.header.multimarkdown - string +Test: And this is a new key-value pair +With-Dash: Test +T: ^^^^^^ meta.header.multimarkdown keyword.other.multimarkdown +T: ^ meta.header.multimarkdown punctuation.separator.key-value.multimarkdown +T: ^^^^ meta.header.multimarkdown string.unquoted.multimarkdown +With Space: Test +T: ^^^^^^^ meta.header.multimarkdown keyword.other.multimarkdown +T: ^ meta.header.multimarkdown punctuation.separator.key-value.multimarkdown +T: ^^^^ meta.header.multimarkdown string.unquoted.multimarkdown +HTML Header: +T: ^^^^^^^^ meta.header.multimarkdown string.unquoted.multimarkdown + +T: +| <- meta.content.multimarkdown - meta.header.multimarkdown +# Heading +| <- markup.heading punctuation.definition.heading +|^^^^^^^^ markup.heading diff --git a/tests/test_folding.md b/tests/test_folding.md new file mode 100644 index 00000000..ed6b3182 --- /dev/null +++ b/tests/test_folding.md @@ -0,0 +1,59 @@ +# 1 Heading + +A paragraph with [link](https://foo.bar). + +* item 1 +* item 2 +* item 3 + +## 1.1 Heading + +### 1.1.1 Heading + +Simple paragraph. + +#### 1.1.1.1 Heading + +A paragraph with [link](https://foo.bar). + +#### 1.1.1.2 Heading + +A paragraph with [^1] footnotes. + +[^1]: Footnote + +### 1.1.2 Heading + +Simple paragraph. + +title | description +--- | --- +foo | bar + +## [1.3](https://foo.bar) Heading + +A paragraph with [link](https://foo.bar). + +## 1.3 Heading + +Simple paragraph. + +# 2 Heading + +Simple paragraph. + +3 heading +========= + +3.1 heading +----------- + +Simple paragraph. + +3.2 heading +----------- +Simple paragraph. + +4 heading +========= +Simple paragraph. diff --git a/tests/test_folding.py b/tests/test_folding.py new file mode 100644 index 00000000..ca243f63 --- /dev/null +++ b/tests/test_folding.py @@ -0,0 +1,792 @@ +import sublime + +from MarkdownEditing.tests import DereferrablePanelTestCase + +# test assets + +from MarkdownEditing.plugins.headings import ( + all_headings +) +from MarkdownEditing.plugins.folding import ( + section_region_and_level +) + + +class FoldingTestCase(DereferrablePanelTestCase): + + @classmethod + def setUpClass(cls): + """ + Create output panel and load text from `test_folding.md` into. + """ + super().setUpClass() + with open(__file__[:-2] + "md") as f: + cls.setText(f.read().replace("\r\n", "\n").replace("\r", "\n")) + + def setUp(self): + self.view.settings().set("mde.auto_fold_link.enabled", True) + + def tearDown(self): + self.view.settings().erase("mde.auto_fold_link.enabled") + self.view.settings().erase("mde.folding.target_level") + + def assertFoldedRegions(self, region_tuples): + self.assertEqual( + self.view.folded_regions(), + list(map(lambda x: sublime.Region(*x), region_tuples)) + ) + + # all_headings() unittests + + def test_all_headings(self): + self.assertEqual( + list(all_headings(self.view)), + [ + (0, 11, 1), + (84, 98, 2), + (100, 117, 3), + (138, 158, 4), + (203, 223, 4), + (275, 292, 3), + (358, 391, 2), + (436, 450, 2), + (471, 482, 1), + (503, 522, 1), + (524, 547, 2), + (568, 591, 2), + (611, 630, 1) + ] + ) + + # test section region of atx heading level 1 + + def test_section_region_and_level__heading_1_bol(self): + self._test_section_region_and_level(1, 1, 11, 470, 1) + + def test_section_region_and_level__heading_1_mol(self): + self._test_section_region_and_level(1, 2, 11, 470, 1) + + def test_section_region_and_level__heading_1_eol(self): + self._test_section_region_and_level(1, 10, 11, 470, 1) + + # test section region of atx heading level 2 + + def test_section_region_and_level__heading_1_1_bol(self): + self._test_section_region_and_level(9, 1, 98, 357, 2) + + def test_section_region_and_level__heading_1_1_mol(self): + self._test_section_region_and_level(9, 5, 98, 357, 2) + + def test_section_region_and_level__heading_11__eol(self): + self._test_section_region_and_level(9, 15, 98, 357, 2) + + # test section region of atx heading level 4 + + def test_section_region_and_level__heading_1_1_1_2_bol(self): + self._test_section_region_and_level(19, 1, 223, 274, 4) + + def test_section_region_and_level__heading_1_1_1_2_mol(self): + self._test_section_region_and_level(19, 2, 223, 274, 4) + + def test_section_region_and_level__heading_11__1_2_eol(self): + self._test_section_region_and_level(19, 15, 223, 274, 4) + + # test section region of setext heading level 1 + + def test_section_region_and_level__setext_heading_3_text_bol(self): + self._test_section_region_and_level(45, 1, 522, 610, 1) + + def test_section_region_and_level__setext_heading_3_underline_bol(self): + self._test_section_region_and_level(46, 1, 522, 610, 1) + + def test_section_region_and_level__setext_heading_3_text_mol(self): + self._test_section_region_and_level(45, 5, 522, 610, 1) + + def test_section_region_and_level__setext_heading_3_underline_mol(self): + self._test_section_region_and_level(46, 5, 522, 610, 1) + + def test_section_region_and_level__setext_heading_3_text_eol(self): + self._test_section_region_and_level(45, 10, 522, 610, 1) + + def test_section_region_and_level__setext_heading_3_underline_eol(self): + self._test_section_region_and_level(46, 10, 522, 610, 1) + + # test section region of setext heading level 2 + + def test_section_region_and_level__setext_heading_3_1_text_bol(self): + self._test_section_region_and_level(48, 1, 547, 567, 2) + + def test_section_region_and_level__setext_heading_3_1_underline_bol(self): + self._test_section_region_and_level(49, 1, 547, 567, 2) + + def test_section_region_and_level__setext_heading_3_1_text_mol(self): + self._test_section_region_and_level(48, 5, 547, 567, 2) + + def test_section_region_and_level__setext_heading_3_1_underline_mol(self): + self._test_section_region_and_level(49, 5, 547, 567, 2) + + def test_section_region_and_level__setext_heading_3_1_text_eol(self): + self._test_section_region_and_level(48, 12, 547, 567, 2) + + def test_section_region_and_level__setext_heading_3_1_underline_eol(self): + self._test_section_region_and_level(49, 12, 547, 567, 2) + + def _test_section_region_and_level(self, row, col, begin, end, level): + self.assertEqual( + section_region_and_level(self.view, self.textPoint(row, col), -1), + (sublime.Region(begin, end), level) + ) + + # test folding and unfolding atx heading level 1 + + def test_fold_section__heading_1_bol(self): + self._test_fold_section__heading_1(1, 1) + + def test_fold_section__heading_1_mol(self): + self._test_fold_section__heading_1(1, 5) + + def test_fold_section__heading_1_eol(self): + self._test_fold_section__heading_1(1, 12) + + def _test_fold_section__heading_1(self, row, col): + # setup test + self.setCaretTo(row, col) + self.view.run_command("unfold_all") + + # fold heading + self.view.run_command("mde_fold_section") + self.assertFoldedRegions([(11, 470)]) + + # unfold heading + self.view.run_command("mde_fold_section") + self.assertFoldedRegions([(37, 52), (184, 199), (367, 382), (417, 432)]) + + # setup test + self.view.settings().set("mde.auto_fold_link.enabled", False) + + # fold heading + self.view.run_command("mde_fold_section") + self.assertFoldedRegions([(11, 470)]) + + # unfold heading + self.view.run_command("mde_fold_section") + self.assertFoldedRegions([]) + + # test folding and unfolding setext heading level 1 + + def test_fold_section__heading_3_text_bol(self): + self._test_fold_section__heading_3(45, 1) + + def test_fold_section__heading_3_text_mol(self): + self._test_fold_section__heading_3(45, 5) + + def test_fold_section__heading_3_text_eol(self): + self._test_fold_section__heading_3(45, 10) + + def test_fold_section__heading_3_underline_bol(self): + self._test_fold_section__heading_3(46, 1) + + def test_fold_section__heading_3_underline_mol(self): + self._test_fold_section__heading_3(46, 2) + + def test_fold_section__heading_3_underline_eol(self): + self._test_fold_section__heading_3(46, 10) + + def _test_fold_section__heading_3(self, row, col): + # setup test + self.setCaretTo(row, col) + self.view.settings().set("mde.auto_fold_link.enabled", False) + self.view.run_command("unfold_all") + + # fold heading + self.view.run_command("mde_fold_section") + self.assertFoldedRegions([(522, 610)]) + + # unfold heading + self.view.run_command("mde_fold_section") + self.assertFoldedRegions([]) + + # test folding and unfolding setext heading level 2 + + def test_fold_section__heading_3_1_text_bol(self): + self._test_fold_section__heading_3_1(48, 1) + + def test_fold_section__heading_3_1_text_mol(self): + self._test_fold_section__heading_3_1(48, 5) + + def test_fold_section__heading_3_1_text_eol(self): + self._test_fold_section__heading_3_1(48, 10) + + def test_fold_section__heading_3_1_underline_bol(self): + self._test_fold_section__heading_3_1(49, 1) + + def test_fold_section__heading_3_1_underline_mol(self): + self._test_fold_section__heading_3_1(49, 2) + + def test_fold_section__heading_3_1_underline_eol(self): + self._test_fold_section__heading_3_1(49, 10) + + def _test_fold_section__heading_3_1(self, row, col): + # setup test + self.setCaretTo(row, col) + self.view.settings().set("mde.auto_fold_link.enabled", False) + self.view.run_command("unfold_all") + + # fold heading + self.view.run_command("mde_fold_section") + self.assertFoldedRegions([(547, 567)]) + + # unfold heading + self.view.run_command("mde_fold_section") + self.assertFoldedRegions([]) + + # test folding and unfolding by level + + def test_fold_all_sections__level_0_without_auto_link_folding(self): + self._test_fold_all_sections_without_auto_link_folding(0, [ + (11, 83), + (98, 99), + (117, 137), + (158, 202), + (223, 274), + (292, 357), + (391, 435), + (450, 470), + (482, 502), + (522, 523), + (547, 567), + (591, 610), + (630, 649) + ]) + + def test_fold_all_sections__level_1_without_auto_link_folding(self): + self._test_fold_all_sections_without_auto_link_folding(1, [ + (11, 470), + (482, 502), + (522, 610), + (630, 649) + ]) + + def test_fold_all_sections__level_2_without_auto_link_folding(self): + self._test_fold_all_sections_without_auto_link_folding(2, [ + (98, 357), + (391, 435), + (450, 470), + (547, 567), + (591, 610) + ]) + + def test_fold_all_sections__level_3_without_auto_link_folding(self): + self._test_fold_all_sections_without_auto_link_folding(3, [ + (117, 274), + (292, 357) + ]) + + def test_fold_all_sections__level_4_without_auto_link_folding(self): + self._test_fold_all_sections_without_auto_link_folding(4, [ + (158, 202), + (223, 274) + ]) + + def test_fold_all_sections__level_5_without_auto_link_folding(self): + self._test_fold_all_sections_without_auto_link_folding(5, []) + + def _test_fold_all_sections_without_auto_link_folding(self, level, expected_regions): + self.view.settings().set("mde.auto_fold_link.enabled", False) + self.view.run_command("mde_fold_all_sections", {"target_level": level}) + self.assertFoldedRegions(expected_regions) + + def test_fold_all_sections__level_0_with_auto_link_folding(self): + self._test_fold_all_sections_with_auto_link_folding(0, [ + (11, 83), + (98, 99), + (117, 137), + (158, 202), + (223, 274), + (292, 357), + (367, 382), + (391, 435), + (450, 470), + (482, 502), + (522, 523), + (547, 567), + (591, 610), + (630, 649) + ]) + + def test_fold_all_sections__level_1_with_auto_link_folding(self): + self._test_fold_all_sections_with_auto_link_folding(1, [ + (11, 470), + (482, 502), + (522, 610), + (630, 649) + ]) + + def test_fold_all_sections__level_2_with_auto_link_folding(self): + self._test_fold_all_sections_with_auto_link_folding(2, [ + (37, 52), + (98, 357), + (367, 382), + (391, 435), + (450, 470), + (547, 567), + (591, 610) + ]) + + def test_fold_all_sections__level_3_with_auto_link_folding(self): + self._test_fold_all_sections_with_auto_link_folding(3, [ + (37, 52), + (117, 274), + (292, 357), + (367, 382), + (417, 432) + ]) + + def test_fold_all_sections__level_4_with_auto_link_folding(self): + self._test_fold_all_sections_with_auto_link_folding(4, [ + (37, 52), + (158, 202), + (223, 274), + (367, 382), + (417, 432) + ]) + + def test_fold_all_sections__level_5_with_auto_link_folding(self): + self._test_fold_all_sections_with_auto_link_folding(5, [ + (37, 52), + (184, 199), + (367, 382), + (417, 432) + ]) + + def _test_fold_all_sections_with_auto_link_folding(self, level, expected_regions): + self.view.run_command("mde_fold_all_sections", {"target_level": level}) + self.assertFoldedRegions(expected_regions) + + def test_unfold_section__heading_1_with_folding_tartet_level_0(self): + # unfold and then fold "1 Heading" + self._test_unfold_section__heading_x_with_folding_tartet_level_0(1, [ + (37, 52), + (98, 99), + (117, 137), + (158, 202), + (223, 274), + (292, 357), + (367, 382), + (391, 435), + (450, 470), + (482, 502), + (522, 523), + (547, 567), + (591, 610), + (630, 649) + ]) + + def test_unfold_section__heading_1_1_with_folding_tartet_level_0(self): + # unfold and then fold "1.1 Heading" + self._test_unfold_section__heading_x_with_folding_tartet_level_0(9, [ + (11, 83), + # (98, 99), + (117, 137), + (158, 202), + (223, 274), + (292, 357), + (367, 382), + (391, 435), + (450, 470), + (482, 502), + (522, 523), + (547, 567), + (591, 610), + (630, 649) + ]) + + def test_unfold_section__heading_1_1_1_with_folding_tartet_level_0(self): + # unfold and then fold "1.1.1 Heading" + self._test_unfold_section__heading_x_with_folding_tartet_level_0(11, [ + (11, 83), + (98, 99), + # (117, 137), + (158, 202), + (223, 274), + (292, 357), + (367, 382), + (391, 435), + (450, 470), + (482, 502), + (522, 523), + (547, 567), + (591, 610), + (630, 649) + ]) + + def test_unfold_section__heading_3_with_folding_tartet_level_0(self): + # unfold and then fold "3 Heading" + self._test_unfold_section__heading_x_with_folding_tartet_level_0(45, [ + (11, 83), + (98, 99), + (117, 137), + (158, 202), + (223, 274), + (292, 357), + (367, 382), + (391, 435), + (450, 470), + (482, 502), + # (522, 523), + (547, 567), + (591, 610), + (630, 649) + ]) + + def test_unfold_section__heading_3_2_with_folding_tartet_level_0(self): + # unfold and then fold "3.2 Heading" + self._test_unfold_section__heading_x_with_folding_tartet_level_0(53, [ + (11, 83), + (98, 99), + (117, 137), + (158, 202), + (223, 274), + (292, 357), + (367, 382), + (391, 435), + (450, 470), + (482, 502), + (522, 523), + (547, 567), + # (591, 610), + (630, 649) + ]) + + def _test_unfold_section__heading_x_with_folding_tartet_level_0(self, row, expected_regions): + # prepare test by folding sections by target_level 0 (outline mode) + # outline mode: Only fold a section up to very next heading! + self.view.run_command("mde_fold_all_sections", {"target_level": 0}) + + # unfold heading + self.setCaretTo(row, 1) + self.view.run_command("mde_fold_section") + self.assertFoldedRegions(expected_regions) + + # fold heading + self.view.run_command("mde_fold_section") + self.assertFoldedRegions([ + (11, 83), + (98, 99), + (117, 137), + (158, 202), + (223, 274), + (292, 357), + (367, 382), + (391, 435), + (450, 470), + (482, 502), + (522, 523), + (547, 567), + (591, 610), + (630, 649) + ]) + + def test_unfold_section__heading_1_with_folding_tartet_level_1(self): + # prepare test by folding sections by target_level 1 + self.view.run_command("mde_fold_all_sections", {"target_level": 1}) + + # unfold "1 Heading" with caret before folding marker + self.setCaretTo(1, 11) + self.view.run_command("mde_fold_section") + self.assertFoldedRegions([ + (37, 52), + (98, 357), + (367, 382), + (391, 435), + (450, 470), + (482, 502), + (522, 610), + (630, 649) + ]) + + # fold "1 Heading" + self.setCaretTo(1, 11) + self.view.run_command("mde_fold_section") + self.assertFoldedRegions([ + (11, 470), + (482, 502), + (522, 610), + (630, 649) + ]) + + # unfold "1 Heading" with caret after folding marker + self.setCaretTo(40, 1) + self.view.run_command("mde_fold_section") + self.assertFoldedRegions([ + (37, 52), + (98, 357), + (367, 382), + (391, 435), + (450, 470), + (482, 502), + (522, 610), + (630, 649) + ]) + + # unfold "1.1 Heading" + self.setCaretTo(9, 9) + self.view.run_command("mde_fold_section") + self.assertFoldedRegions([ + (37, 52), + (117, 274), + (292, 357), + (367, 382), + (391, 435), + (450, 470), + (482, 502), + (522, 610), + (630, 649) + ]) + + # unfold "1.1.2 Heading" + self.setCaretTo(25, 9) + self.view.run_command("mde_fold_section") + self.assertFoldedRegions([ + (37, 52), + (117, 274), + (367, 382), + (391, 435), + (450, 470), + (482, 502), + (522, 610), + (630, 649) + ]) + + # fold "1.1 Heading" + self.setCaretTo(9, 9) + self.view.run_command("mde_fold_section") + self.assertFoldedRegions([ + (37, 52), + (98, 357), + (367, 382), + (391, 435), + (450, 470), + (482, 502), + (522, 610), + (630, 649) + ]) + + def test_fold_links_command__target_level_none(self): + # setup initial state with all sections unfolded + self.setCaretTo(1, 1) + self.view.run_command("mde_unfold_all_sections") + + # disable automatic link folding + self.view.run_command("mde_fold_links", {"fold": False}) + self.assertFoldedRegions([]) + + # enable automatic link folding + self.view.run_command("mde_fold_links", {"fold": True}) + self.assertFoldedRegions([ + (37, 52), + (184, 199), + (367, 382), + (417, 432) + ]) + + def test_fold_links_command__target_level_0(self): + # prepare test by folding sections by target_level 0 (outline-mode) + self.setCaretTo(1, 1) + self.view.run_command("mde_fold_all_sections", {"target_level": 0}) + + # disable automatic link folding + self.view.run_command("mde_fold_links", {"fold": False}) + self.assertFoldedRegions([ + (11, 83), + (98, 99), + (117, 137), + (158, 202), + (223, 274), + (292, 357), + # (367, 382), + (391, 435), + (450, 470), + (482, 502), + (522, 523), + (547, 567), + (591, 610), + (630, 649) + ]) + + # enable automatic link folding + self.view.run_command("mde_fold_links", {"fold": True}) + self.assertFoldedRegions([ + (11, 83), + (98, 99), + (117, 137), + (158, 202), + (223, 274), + (292, 357), + (367, 382), + (391, 435), + (450, 470), + (482, 502), + (522, 523), + (547, 567), + (591, 610), + (630, 649) + ]) + + def test_fold_links_command__target_level_1(self): + # no link is visible, thus folded regions must not change + expected_regions = [ + (11, 470), + (482, 502), + (522, 610), + (630, 649) + ] + + # prepare test by folding sections by target_level 1 + self.setCaretTo(1, 1) + self.view.run_command("mde_fold_all_sections", {"target_level": 1}) + + # disable automatic link folding + self.view.run_command("mde_fold_links", {"fold": False}) + self.assertFoldedRegions(expected_regions) + + # enable automatic link folding + self.view.run_command("mde_fold_links", {"fold": True}) + self.assertFoldedRegions(expected_regions) + + def test_fold_links_command__target_level_2(self): + # prepare test by folding sections by target_level 1 + self.setCaretTo(1, 1) + self.view.run_command("mde_fold_all_sections", {"target_level": 2}) + + # disable automatic link folding + self.view.run_command("mde_fold_links", {"fold": False}) + self.assertFoldedRegions([ + (98, 357), + (391, 435), + (450, 470), + (547, 567), + (591, 610) + ]) + + # enable automatic link folding + self.view.run_command("mde_fold_links", {"fold": True}) + self.assertFoldedRegions([ + (37, 52), + (98, 357), + (367, 382), + (391, 435), + (450, 470), + (547, 567), + (591, 610) + ]) + + def test_fold_links_command__target_level_3(self): + # prepare test by folding sections by target_level 1 + self.setCaretTo(1, 1) + self.view.run_command("mde_fold_all_sections", {"target_level": 3}) + + # disable automatic link folding + self.view.run_command("mde_fold_links", {"fold": False}) + self.assertFoldedRegions([ + (117, 274), + (292, 357) + ]) + + # enable automatic link folding + self.view.run_command("mde_fold_links", {"fold": True}) + self.assertFoldedRegions([ + (37, 52), + (117, 274), + (292, 357), + (367, 382), + (417, 432) + ]) + + def test_auto_fold_links__target_level_none(self): + # setup initial state with all sections unfolded + self.setCaretTo(1, 1) + self.view.run_command("mde_unfold_all_sections") + + # caret not within a link url, all folded + self.setCaretTo(1, 1) + self.assertFoldedRegions([ + (37, 52), + (184, 199), + (367, 382), + (417, 432) + ]) + + # caret at beginning of url in line 3 (unfolded) + self.setCaretTo(3, 25) + self.view.run_command("mde_fold_links", {"fold": True}) + self.assertFoldedRegions([ + # (37, 52), + (184, 199), + (367, 382), + (417, 432) + ]) + + # caret at end of url in line 3 (unfolded) + self.setCaretTo(3, 40) + self.view.run_command("mde_fold_links", {"fold": True}) + self.assertFoldedRegions([ + # (37, 52), + (184, 199), + (367, 382), + (417, 432) + ]) + + # select url in line 3 (unfolded) + self.view.sel().clear() + self.view.sel().add(sublime.Region(self.textPoint(3, 25), self.textPoint(3, 40))) + self.view.run_command("mde_fold_links", {"fold": True}) + self.assertFoldedRegions([ + # (37, 52), + (184, 199), + (367, 382), + (417, 432) + ]) + + # select line 3 (all folded) + self.view.sel().clear() + self.view.sel().add(self.view.line(self.textPoint(3, 25))) + self.view.run_command("mde_fold_links", {"fold": True}) + self.assertFoldedRegions([ + (37, 52), + (184, 199), + (367, 382), + (417, 432) + ]) + + def test_folded_links_when_editing_content(self): + # setup initial state with all sections unfolded + self.setCaretTo(3, 2) + self.view.run_command("mde_unfold_all_sections") + self.assertFoldedRegions([ + (37, 52), + (184, 199), + (367, 382), + (417, 432) + ]) + + # caret between "A" and "paragraph" and insert "new " + # make sure following regions move accordingly + self.view.run_command("insert", {"characters": "new "}) + self.assertFoldedRegions([ + (41, 56), + (188, 203), + (371, 386), + (421, 436) + ]) + + # delete "new " again to restore previous state + self.view.sel().clear() + self.view.sel().add(sublime.Region(self.textPoint(3, 2), self.textPoint(3, 6))) + self.view.run_command("left_delete") + self.assertFoldedRegions([ + (37, 52), + (184, 199), + (367, 382), + (417, 432) + ]) diff --git a/tests/test_join_lines.py b/tests/test_join_lines.py new file mode 100644 index 00000000..58d47edb --- /dev/null +++ b/tests/test_join_lines.py @@ -0,0 +1,587 @@ +from MarkdownEditing.tests import DereferrablePanelTestCase + + +class JoinListItemsTestCase(DereferrablePanelTestCase): + + def test_join_two_ordered_list_items_with_dot(self): + self.setBlockText( + """ + 1. item 1 + 2. item 2 + """ + ) + self.setCaretTo(1, 8) + self.view.run_command("mde_join_lines") + self.assertEqualBlockText( + """ + 1. item 1 item 2 + """ + ) + + def test_join_two_ordered_list_items_with_paren(self): + self.setBlockText( + """ + 1) item 1 + 2) item 2 + """ + ) + self.setCaretTo(1, 8) + self.view.run_command("mde_join_lines") + self.assertEqualBlockText( + """ + 1) item 1 item 2 + """ + ) + + def test_join_two_unordered_list_items(self): + self.setBlockText( + """ + * item 1 + * item 2 + """ + ) + self.setCaretTo(1, 8) + self.view.run_command("mde_join_lines") + self.assertEqualBlockText( + """ + * item 1 item 2 + """ + ) + + def test_join_ordered_list_with_subitems(self): + self.setBlockText( + """ + 1) item 1 + - foo + - bar + 2) item 2 + """ + ) + self.setCaretTo(2, 1) + self.view.run_command("mde_join_lines") + self.assertEqualBlockText( + """ + 1) item 1 + - foo bar + 2) item 2 + """ + ) + + self.setCaretTo(2, 1) + self.view.run_command("mde_join_lines") + self.assertEqualBlockText( + """ + 1) item 1 + - foo bar item 2 + """ + ) + + self.setCaretTo(1, 1) + self.view.run_command("mde_join_lines") + self.assertEqualText("1) item 1 foo bar item 2") + + def test_join_unordered_list_with_subitems(self): + self.setBlockText( + """ + * item 1 + - foo + - bar + * item 2 + """ + ) + self.setCaretTo(2, 1) + self.view.run_command("mde_join_lines") + self.assertEqualBlockText( + """ + * item 1 + - foo bar + * item 2 + """ + ) + + self.setCaretTo(2, 1) + self.view.run_command("mde_join_lines") + self.assertEqualBlockText( + """ + * item 1 + - foo bar item 2 + """ + ) + + self.setCaretTo(1, 1) + self.view.run_command("mde_join_lines") + self.assertEqualText("* item 1 foo bar item 2") + + def test_join_ordered_list_with_subitems_multi_caret(self): + self.setBlockText( + """ + 1) item 1 + - foo + - bar + 2) item 2 + """ + ) + self.setCaretTo(1, 3) + self.addCaretAt(2, 3) + self.addCaretAt(3, 3) + self.view.run_command("mde_join_lines") + self.assertEqualText("1) item 1 foo bar item 2") + + def test_join_unordered_list_with_subitems_multi_caret(self): + self.setBlockText( + """ + * item 1 + - foo + - bar + * item 2 + """ + ) + self.setCaretTo(1, 3) + self.addCaretAt(2, 3) + self.addCaretAt(3, 3) + self.view.run_command("mde_join_lines") + self.assertEqualText("* item 1 foo bar item 2") + + def test_join_ordered_list_with_text_multi_caret(self): + self.setBlockText( + """ + 1) item 1 + foo + bar + 2) item 2 + """ + ) + self.setCaretTo(1, 3) + self.addCaretAt(2, 3) + self.addCaretAt(3, 3) + self.view.run_command("mde_join_lines") + self.assertEqualText("1) item 1 foo bar item 2") + + def test_join_unordered_list_with_text_multi_caret(self): + self.setBlockText( + """ + * item 1 + bar + baz + * item + """ + ) + self.setCaretTo(1, 3) + self.addCaretAt(2, 3) + self.addCaretAt(3, 3) + self.view.run_command("mde_join_lines") + self.assertEqualText("* item 1 bar baz item") + + def test_join_selected_ordered_list_with_subitems(self): + self.setBlockText( + """ + 1) item 1 + - foo + - bar + 2) item 2 + """ + ) + self.view.run_command("select_all") + self.view.run_command("mde_join_lines") + self.assertEqualText("1) item 1 foo bar item 2") + + def test_join_selected_unordered_list_with_subitems(self): + self.setBlockText( + """ + * item 1 + - foo + - bar + * item 2 + """ + ) + self.view.run_command("select_all") + self.view.run_command("mde_join_lines") + self.assertEqualText("* item 1 foo bar item 2") + + def test_join_selected_ordered_list_with_text(self): + self.setBlockText( + """ + 1) item 1 + foo + bar + 2) item 2 + """ + ) + self.view.run_command("select_all") + self.view.run_command("mde_join_lines") + self.assertEqualText("1) item 1 foo bar item 2") + + def test_join_selected_unordered_list_with_text(self): + self.setBlockText( + """ + * item 1 + bar + baz + * item + """ + ) + self.view.run_command("select_all") + self.view.run_command("mde_join_lines") + self.assertEqualText("* item 1 bar baz item") + + def test_join_lines_keep_ordered_list_bullet(self): + self.setBlockText( + """ + # Heading + + + 1. item 1 + """ + ) + self.setCaretTo(3, 1) + self.view.run_command("mde_join_lines") + self.assertEqualBlockText( + """ + # Heading + + 1. item 1 + """ + ) + + def test_join_lines_keep_unordered_list_bullet(self): + self.setBlockText( + """ + # Heading + + + * item 1 + """ + ) + self.setCaretTo(3, 1) + self.view.run_command("mde_join_lines") + self.assertEqualBlockText( + """ + # Heading + + * item 1 + """ + ) + + +class JoinBlockQuoteLinesTestCase(DereferrablePanelTestCase): + + def test_join_selected_text_level1(self): + self.setBlockText( + """ + > foo + > bar + > baz + """ + ) + self.view.run_command("select_all") + self.view.run_command("mde_join_lines") + self.assertEqualText("> foo bar baz") + + def test_join_selected_text_level2(self): + self.setBlockText( + """ + > > foo + > > bar + > baz + """ + ) + self.view.run_command("select_all") + self.view.run_command("mde_join_lines") + self.assertEqualText("> > foo bar baz") + + def test_join_two_ordered_list_items_with_dot(self): + self.setBlockText( + """ + > 1. item 1 + > 2. item 2 + """ + ) + self.setCaretTo(1, 8) + self.view.run_command("mde_join_lines") + self.assertEqualBlockText( + """ + > 1. item 1 item 2 + """ + ) + + def test_join_two_ordered_list_items_with_paren(self): + self.setBlockText( + """ + > 1) item 1 + > 2) item 2 + """ + ) + self.setCaretTo(1, 8) + self.view.run_command("mde_join_lines") + self.assertEqualBlockText( + """ + > 1) item 1 item 2 + """ + ) + + def test_join_two_unordered_list_items(self): + self.setBlockText( + """ + > * item 1 + > * item 2 + """ + ) + self.setCaretTo(1, 8) + self.view.run_command("mde_join_lines") + self.assertEqualBlockText( + """ + > * item 1 item 2 + """ + ) + + def test_join_ordered_list_with_subitems(self): + self.setBlockText( + """ + > 1) item 1 + > - foo + > - bar + > 2) item 2 + """ + ) + self.setCaretTo(2, 1) + self.view.run_command("mde_join_lines") + self.assertEqualBlockText( + """ + > 1) item 1 + > - foo bar + > 2) item 2 + """ + ) + + self.setCaretTo(2, 1) + self.view.run_command("mde_join_lines") + self.assertEqualBlockText( + """ + > 1) item 1 + > - foo bar item 2 + """ + ) + + self.setCaretTo(1, 1) + self.view.run_command("mde_join_lines") + self.assertEqualText("> 1) item 1 foo bar item 2") + + def test_join_unordered_list_with_subitems(self): + self.setBlockText( + """ + > * item 1 + > - foo + > - bar + > * item 2 + """ + ) + self.setCaretTo(2, 1) + self.view.run_command("mde_join_lines") + self.assertEqualBlockText( + """ + > * item 1 + > - foo bar + > * item 2 + """ + ) + + self.setCaretTo(2, 1) + self.view.run_command("mde_join_lines") + self.assertEqualBlockText( + """ + > * item 1 + > - foo bar item 2 + """ + ) + + self.setCaretTo(1, 1) + self.view.run_command("mde_join_lines") + self.assertEqualText("> * item 1 foo bar item 2") + + def test_join_ordered_list_with_subitems_multi_caret(self): + self.setBlockText( + """ + > 1) item 1 + > - foo + > - bar + > 2) item 2 + """ + ) + self.setCaretTo(1, 3) + self.addCaretAt(2, 3) + self.addCaretAt(3, 3) + self.view.run_command("mde_join_lines") + self.assertEqualText("> 1) item 1 foo bar item 2") + + def test_join_unordered_list_with_subitems_multi_caret(self): + self.setBlockText( + """ + > * item 1 + > - foo + > - bar + > * item 2 + """ + ) + self.setCaretTo(1, 3) + self.addCaretAt(2, 3) + self.addCaretAt(3, 3) + self.view.run_command("mde_join_lines") + self.assertEqualText("> * item 1 foo bar item 2") + + def test_join_ordered_list_with_text_multi_caret(self): + self.setBlockText( + """ + > 1) item 1 + > foo + > bar + > 2) item 2 + """ + ) + self.setCaretTo(1, 3) + self.addCaretAt(2, 3) + self.addCaretAt(3, 3) + self.view.run_command("mde_join_lines") + self.assertEqualText("> 1) item 1 foo bar item 2") + + def test_join_unordered_list_with_text_multi_caret(self): + self.setBlockText( + """ + > * item 1 + > bar + > baz + > * item + """ + ) + self.setCaretTo(1, 3) + self.addCaretAt(2, 3) + self.addCaretAt(3, 3) + self.view.run_command("mde_join_lines") + self.assertEqualText("> * item 1 bar baz item") + + def test_join_selected_ordered_list_with_subitems(self): + self.setBlockText( + """ + > 1) item 1 + > - foo + > - bar + > 2) item 2 + """ + ) + self.view.run_command("select_all") + self.view.run_command("mde_join_lines") + self.assertEqualText("> 1) item 1 foo bar item 2") + + def test_join_selected_unordered_list_with_subitems(self): + self.setBlockText( + """ + > * item 1 + > - foo + > - bar + > * item 2 + """ + ) + self.view.run_command("select_all") + self.view.run_command("mde_join_lines") + self.assertEqualText("> * item 1 foo bar item 2") + + def test_join_selected_ordered_list_with_text(self): + self.setBlockText( + """ + > 1) item 1 + > foo + > bar + > 2) item 2 + """ + ) + self.view.run_command("select_all") + self.view.run_command("mde_join_lines") + self.assertEqualText("> 1) item 1 foo bar item 2") + + def test_join_selected_unordered_list_with_text(self): + self.setBlockText( + """ + > * item 1 + > bar + > baz + > * item + """ + ) + self.view.run_command("select_all") + self.view.run_command("mde_join_lines") + self.assertEqualText("> * item 1 bar baz item") + + def test_join_lines_keep_ordered_list_bullet_if_caret_after_blockquote_sign(self): + self.setBlockText( + """ + > # Heading + >\x20 + >\x20 + > 1. item 1 + """ + ) + self.setCaretTo(3, 3) + self.view.run_command("mde_join_lines") + self.assertEqualBlockText( + """ + > # Heading + >\x20 + > 1. item 1 + """ + ) + + def test_join_lines_keep_unordered_list_bullet_if_caret_after_blockquote_sign(self): + self.setBlockText( + """ + > # Heading + >\x20 + >\x20 + > * item 1 + """ + ) + self.setCaretTo(3, 3) + self.view.run_command("mde_join_lines") + self.assertEqualBlockText( + """ + > # Heading + >\x20 + > * item 1 + """ + ) + + def test_join_lines_keep_ordered_list_bullet_if_caret_at_bol(self): + self.setBlockText( + """ + > # Heading + >\x20 + >\x20 + > 1. item 1 + """ + ) + self.setCaretTo(3, 1) + self.view.run_command("mde_join_lines") + self.assertEqualBlockText( + """ + > # Heading + >\x20 + > 1. item 1 + """ + ) + + def test_join_lines_keep_unordered_list_bullet_if_caret_at_bol(self): + self.setBlockText( + """ + > # Heading + >\x20 + >\x20 + > * item 1 + """ + ) + self.setCaretTo(3, 1) + self.view.run_command("mde_join_lines") + self.assertEqualBlockText( + """ + > # Heading + >\x20 + > * item 1 + """ + ) diff --git a/tests/test_json.py b/tests/test_json.py new file mode 100644 index 00000000..212e82ec --- /dev/null +++ b/tests/test_json.py @@ -0,0 +1,255 @@ +""" +Validate JSON format. + +Licensed under MIT +Copyright (c) 2012-2015 Isaac Muse + +Some smaller fixes are applied by +""" +import codecs +import fnmatch +import json +import os +import re +import unittest + +RE_LINE_PRESERVE = re.compile(r'\r?\n', re.MULTILINE) +RE_COMMENT = re.compile( + r'''(?x) + (?P + /\*[^*]*\*+(?:[^/*][^*]*\*+)*/ # multi-line comments + | [ \t]*//(?:[^\r\n])* # single line comments + ) + | (?P + "(?:\\.|[^"\\])*" # double quotes + | .[^/"']* # everything else + ) + ''', + re.DOTALL +) +RE_TRAILING_COMMA = re.compile( + r'''(?x) + ( + (?P + , # trailing comma + (?P[\s\r\n]*) # white space + (?P\]) # bracket + ) + | (?P + , # trailing comma + (?P[\s\r\n]*) # white space + (?P\}) # bracket + ) + ) + | (?P + "(?:\\.|[^"\\])*" # double quoted string + | .[^,"']* # everything else + ) + ''', + re.DOTALL +) +RE_LINE_INDENT_TAB = re.compile( + r'^(?:(\t+)?(?:(/\*)|[^ \t\r\n])[^\r\n]*)?\r?\n$') +RE_LINE_INDENT_SPACE = re.compile( + r'^(?:((?: {4})+)?(?:(/\*)|[^ \t\r\n])[^\r\n]*)?\r?\n$') +RE_LINE_INDENT = [RE_LINE_INDENT_SPACE, RE_LINE_INDENT_TAB] +RE_TRAILING_SPACES = re.compile(r'^.*?[ \t]+\r?\n?$') +RE_COMMENT_END = re.compile(r'\*/') +PA_COMMENT_INDENT_SPACE = r'^(%s *?[^\t\r\n][^\r\n]*)?\r?\n$' +PA_COMMENT_INDENT_TAB = r'^(%s[ \t]*[^ \t\r\n][^\r\n]*)?\r?\n$' +PA_COMMENT_INDENT = [PA_COMMENT_INDENT_SPACE, PA_COMMENT_INDENT_TAB] + +E_MALFORMED = 'E0' +E_COMMENTS = 'E1' +E_COMMA = 'E2' +W_NL_START = 'W1' +W_NL_END = 'W2' +W_INDENT = 'W3' +W_TRAILING_SPACE = 'W4' +W_COMMENT_INDENT = 'W5' + + +VIOLATION_MSG = { + E_MALFORMED: 'JSON content is malformed.', + E_COMMENTS: 'Comments are not part of the JSON spec.', + E_COMMA: 'Dangling comma found.', + W_NL_START: 'Unnecessary newlines at the start of file.', + W_NL_END: 'Missing a new line at the end of the file.', + W_INDENT: 'Indentation Error.', + W_TRAILING_SPACE: 'Trailing whitespace.', + W_COMMENT_INDENT: 'Comment Indentation Error.' +} + + +class CheckJsonFormat(object): + """Test JSON for format irregularities. + + - Trailing spaces. + - Inconsistent indentation. + - New lines at end of file. + - Unnecessary newlines at start of file. + - Trailing commas. + - Malformed JSON. + """ + + def __init__(self, use_tabs=False, allow_comments=False): + """Setup the settings.""" + self.use_tabs = use_tabs + self.allow_comments = allow_comments + self.fail = False + + def index_lines(self, text): + """Index the char range of each line.""" + self.line_range = [] + count = 1 + last = 0 + for m in re.finditer('\n', text): + self.line_range.append((last, m.end(0) - 1, count)) + last = m.end(0) + count += 1 + + def get_line(self, pt): + """Get the line from char index.""" + line = None + for r in self.line_range: + if pt >= r[0] and pt <= r[1]: + line = r[2] + break + return line + + def check_comments(self, text): + """Check for JavaScript comments. + + Log them and strip them out so we can continue. + """ + def remove_comments(group): + return ''.join([x[0] for x in RE_LINE_PRESERVE.findall(group)]) + + def evaluate(m): + text = '' + g = m.groupdict() + if g['code'] is None: + if not self.allow_comments: + self.log_failure(E_COMMENTS, self.get_line(m.start(0))) + text = remove_comments(g['comments']) + else: + text = g['code'] + return text + + return ''.join(map(lambda m: evaluate(m), RE_COMMENT.finditer(text))) + + def check_dangling_commas(self, text): + """Check for dangling commas. + + Log them and strip them out so we can continue. + """ + def check_comma(g, m, line): + # ,] -> ] or ,} -> } + self.log_failure(E_COMMA, line) + if g['square_comma'] is not None: + return g['square_ws'] + g['square_bracket'] + else: + return g['curly_ws'] + g['curly_bracket'] + + def evaluate(m): + g = m.groupdict() + return check_comma( + g, m, self.get_line(m.start(0)) + ) if g['code'] is None else g['code'] + + return ''.join( + map(lambda m: evaluate(m), RE_TRAILING_COMMA.finditer(text))) + + def log_failure(self, code, line=None): + """Log failure. + + Log failure code, line number (if available) and message. + """ + if line: + print('%s: Line %d - %s' % (code, line, VIOLATION_MSG[code])) + else: + print('%s: %s' % (code, VIOLATION_MSG[code])) + self.fail = True + + def check_format(self, file_name): + """Initiate the check.""" + self.fail = False + comment_align = None + with codecs.open(file_name, encoding='utf-8') as f: + count = 1 + for line in f: + indent_match = RE_LINE_INDENT[self.use_tabs].match(line) + end_comment = (comment_align is not None and + RE_COMMENT_END.search(line)) + # Don't allow empty lines at file start. + if count == 1 and line.strip() == '': + self.log_failure(W_NL_START, count) + # Line must end in new line + if not line.endswith('\n'): + self.log_failure(W_NL_END, count) + # Trailing spaces + if RE_TRAILING_SPACES.match(line): + self.log_failure(W_TRAILING_SPACE, count) + # Handle block comment content indentation + if comment_align is not None: + if comment_align.match(line) is None: + self.log_failure(W_COMMENT_INDENT, count) + if end_comment: + comment_align = None + # Handle general indentation + elif indent_match is None: + self.log_failure(W_INDENT, count) + # Enter into block comment + elif comment_align is None and indent_match.group(2): + alignment = indent_match.group(1) or '' + if not end_comment: + comment_align = re.compile( + PA_COMMENT_INDENT[self.use_tabs] % alignment) + count += 1 + f.seek(0) + text = f.read() + + self.index_lines(text) + text = self.check_comments(text) + self.index_lines(text) + text = self.check_dangling_commas(text) + try: + json.loads(text) + except Exception as e: + self.log_failure(E_MALFORMED) + print(e) + return self.fail + + +class TestSublimeResources(unittest.TestCase): + """Test Sublime JSON resource files.""" + + def _get_files(self, patterns, folder='.'): + ignored = {'.git', '.mypy_cache', '.pytest_cache', '.tox', '.venv'} + for root, dirnames, filenames in os.walk(folder): + if any(i in root for i in ignored): + continue + for pattern in patterns: + for filename in fnmatch.filter(filenames, pattern): + yield os.path.join(root, filename) + + def test_json(self): + print() # add a new line to console output before printing file names + patterns = ( + '*.json', + '*.sublime-color-scheme', + '*.sublime-commands', + '*.sublime-keymap', + '*.sublime-menu', + '*.sublime-mousemap', + '*.sublime-settings', + '*.sublime-settings-hints', + '*.sublime-theme' + ) + result = False + folder = os.path.dirname(os.path.dirname(__file__)) + for file in self._get_files(patterns, folder=folder): + print('checking %s ... ' % file) + result |= CheckJsonFormat(True, True).check_format(file) + + self.assertFalse(result, 'At least one JSON file contains errors!') diff --git a/tests/test_number_list.py b/tests/test_number_list.py new file mode 100644 index 00000000..e382264e --- /dev/null +++ b/tests/test_number_list.py @@ -0,0 +1,575 @@ +from MarkdownEditing.tests import DereferrablePanelTestCase + + +class MdeNumberListTestCase(DereferrablePanelTestCase): + + def setUp(self): + self.view.settings().set("mde.auto_increment_ordered_list_number", True) + + def test_add_2nd_item_with_dot_and_one_space(self): + self.setBlockText( + """ + 1. item 1 + """ + ) + self.setCaretTo(1, 10) + self.view.run_command("mde_number_list") + self.assertEqualBlockText( + """ + 1. item 1 + 2.\x20 + """ + ) + + def test_add_2nd_item_with_dot_and_two_spaces(self): + self.setBlockText( + """ + 1. item 1 + """ + ) + self.setCaretTo(1, 11) + self.view.run_command("mde_number_list") + self.assertEqualBlockText( + """ + 1. item 1 + 2.\x20\x20 + """ + ) + + def test_add_2nd_item_with_paren_and_one_space(self): + self.setBlockText( + """ + 1) item 1 + """ + ) + self.setCaretTo(1, 10) + self.view.run_command("mde_number_list") + self.assertEqualBlockText( + """ + 1) item 1 + 2)\x20 + """ + ) + + def test_add_2nd_item_with_paren_and_two_spaces(self): + self.setBlockText( + """ + 1) item 1 + """ + ) + self.setCaretTo(1, 11) + self.view.run_command("mde_number_list") + self.assertEqualBlockText( + """ + 1) item 1 + 2)\x20\x20 + """ + ) + + def test_add_10th_item_with_dot_and_one_space(self): + self.setBlockText( + """ + 9. item 9 + """ + ) + self.setCaretTo(1, 10) + self.view.run_command("mde_number_list") + self.assertEqualBlockText( + """ + 9. item 9 + 10.\x20 + """ + ) + + def test_add_10th_item_with_dot_and_two_spaces(self): + self.setBlockText( + """ + 9. item 9 + """ + ) + self.setCaretTo(1, 11) + self.view.run_command("mde_number_list") + self.assertEqualBlockText( + """ + 9. item 9 + 10.\x20 + """ + ) + + def test_add_10th_item_with_paren_and_one_space(self): + self.setBlockText( + """ + 9) item 9 + """ + ) + self.setCaretTo(1, 10) + self.view.run_command("mde_number_list") + self.assertEqualBlockText( + """ + 9) item 9 + 10)\x20 + """ + ) + + def test_add_10th_item_with_paren_and_two_spaces(self): + self.setBlockText( + """ + 9) item 9 + """ + ) + self.setCaretTo(1, 11) + self.view.run_command("mde_number_list") + self.assertEqualBlockText( + """ + 9) item 9 + 10)\x20 + """ + ) + + def test_insert_2nd_item_with_dot_and_one_space(self): + self.setBlockText( + """ + 1. item 1 + 2. item 2 + """ + ) + self.setCaretTo(1, 10) + self.view.run_command("mde_number_list") + self.assertEqualBlockText( + """ + 1. item 1 + 2.\x20 + 2. item 2 + """ + ) + + def test_insert_2nd_item_with_dot_and_two_spaces(self): + self.setBlockText( + """ + 1. item 1 + 2. item 2 + """ + ) + self.setCaretTo(1, 11) + self.view.run_command("mde_number_list") + self.assertEqualBlockText( + """ + 1. item 1 + 2.\x20\x20 + 2. item 2 + """ + ) + + def test_insert_2nd_item_with_paren_and_one_space(self): + self.setBlockText( + """ + 1) item 1 + 2) item 2 + """ + ) + self.setCaretTo(1, 10) + self.view.run_command("mde_number_list") + self.assertEqualBlockText( + """ + 1) item 1 + 2)\x20 + 2) item 2 + """ + ) + + def test_insert_2nd_item_with_paren_and_two_spaces(self): + self.setBlockText( + """ + 1) item 1 + 2) item 2 + """ + ) + self.setCaretTo(1, 11) + self.view.run_command("mde_number_list") + self.assertEqualBlockText( + """ + 1) item 1 + 2)\x20\x20 + 2) item 2 + """ + ) + + def test_move_2nd_item_with_dot_and_one_space_caret_at_col3(self): + self.setBlockText( + """ + 1. item 1 + 2. item 2 + """ + ) + self.setCaretTo(2, 3) + self.view.run_command("mde_number_list") + self.assertEqualBlockText( + """ + 1. item 1 + 2. + 3. item 2 + """ + ) + + def test_move_2nd_item_with_dot_and_one_space_caret_at_col4(self): + self.setBlockText( + """ + 1. item 1 + 2. item 2 + """ + ) + self.setCaretTo(2, 4) + self.view.run_command("mde_number_list") + self.assertEqualBlockText( + """ + 1. item 1 + 2.\x20 + 3. item 2 + """ + ) + + def test_move_2nd_item_with_paren_and_one_space_caret_at_col3(self): + self.setBlockText( + """ + 1) item 1 + 2) item 2 + """ + ) + self.setCaretTo(2, 3) + self.view.run_command("mde_number_list") + self.assertEqualBlockText( + """ + 1) item 1 + 2) + 3) item 2 + """ + ) + + def test_move_2nd_item_with_paren_and_one_space_caret_at_col4(self): + self.setBlockText( + """ + 1) item 1 + 2) item 2 + """ + ) + self.setCaretTo(2, 4) + self.view.run_command("mde_number_list") + self.assertEqualBlockText( + """ + 1) item 1 + 2)\x20 + 3) item 2 + """ + ) + + def test_move_9th_item_with_dot_and_one_space_caret_at_col3(self): + self.setBlockText( + """ + 8. item 1 + 9. item 2 + """ + ) + self.setCaretTo(2, 3) + self.view.run_command("mde_number_list") + self.assertEqualBlockText( + """ + 8. item 1 + 9. + 10. item 2 + """ + ) + + def test_move_9th_item_with_dot_and_one_space_caret_at_col4(self): + self.setBlockText( + """ + 8. item 1 + 9. item 2 + """ + ) + self.setCaretTo(2, 4) + self.view.run_command("mde_number_list") + self.assertEqualBlockText( + """ + 8. item 1 + 9.\x20 + 10. item 2 + """ + ) + + def test_move_9th_item_with_dot_and_two_spaces_caret_at_col3(self): + # TODO: first two spaces after number need special treatment + # to keep item 2 aligned + self.setBlockText( + """ + 8. item 1 + 9. item 2 + """ + ) + self.setCaretTo(2, 3) + self.view.run_command("mde_number_list") + self.assertEqualBlockText( + """ + 8. item 1 + 9. + 10. item 2 + """ + ) + + def test_move_9th_item_with_dot_and_two_spaces_caret_at_col4(self): + self.setBlockText( + """ + 8. item 1 + 9. item 2 + """ + ) + self.setCaretTo(2, 4) + self.view.run_command("mde_number_list") + self.assertEqualBlockText( + """ + 8. item 1 + 9.\x20 + 10. item 2 + """ + ) + + def test_move_9th_item_with_dot_and_two_spaces_caret_at_col5(self): + self.setBlockText( + """ + 8. item 1 + 9. item 2 + """ + ) + self.setCaretTo(2, 5) + self.view.run_command("mde_number_list") + self.assertEqualBlockText( + """ + 8. item 1 + 9.\x20\x20 + 10. item 2 + """ + ) + + def test_move_9th_item_with_paren_and_one_space_caret_at_col3(self): + self.setBlockText( + """ + 8) item 1 + 9) item 2 + """ + ) + self.setCaretTo(2, 3) + self.view.run_command("mde_number_list") + self.assertEqualBlockText( + """ + 8) item 1 + 9) + 10) item 2 + """ + ) + + def test_move_9th_item_with_paren_and_one_space_caret_at_col4(self): + self.setBlockText( + """ + 8) item 1 + 9) item 2 + """ + ) + self.setCaretTo(2, 4) + self.view.run_command("mde_number_list") + self.assertEqualBlockText( + """ + 8) item 1 + 9)\x20 + 10) item 2 + """ + ) + + def test_move_9th_item_with_paren_and_two_spaces_caret_at_col3(self): + # TODO: first two spaces after number need special treatment + # to keep item 2 aligned + self.setBlockText( + """ + 8) item 1 + 9) item 2 + """ + ) + self.setCaretTo(2, 3) + self.view.run_command("mde_number_list") + self.assertEqualBlockText( + """ + 8) item 1 + 9) + 10) item 2 + """ + ) + + def test_move_9th_item_with_paren_and_two_spaces_caret_at_col4(self): + self.setBlockText( + """ + 8) item 1 + 9) item 2 + """ + ) + self.setCaretTo(2, 4) + self.view.run_command("mde_number_list") + self.assertEqualBlockText( + """ + 8) item 1 + 9)\x20 + 10) item 2 + """ + ) + + def test_move_9th_item_with_paren_and_two_spaces_caret_at_col5(self): + self.setBlockText( + """ + 8) item 1 + 9) item 2 + """ + ) + self.setCaretTo(2, 5) + self.view.run_command("mde_number_list") + self.assertEqualBlockText( + """ + 8) item 1 + 9)\x20\x20 + 10) item 2 + """ + ) + + def test_split_1st_item_with_dot_and_one_space_before_space(self): + # Note: doesn't trim white spaces + self.setBlockText( + """ + 1. item 1 item 2 + """ + ) + self.setCaretTo(1, 10) + self.view.run_command("mde_number_list") + self.assertEqualBlockText( + """ + 1. item 1 + 2. item 2 + """ + ) + + def test_split_1st_item_with_dot_and_one_space_after_space(self): + # Note: doesn't trim white spaces + self.setBlockText( + """ + 1. item 1 item 2 + """ + ) + self.setCaretTo(1, 11) + self.view.run_command("mde_number_list") + self.assertEqualBlockText( + """ + 1. item 1\x20 + 2. item 2 + """ + ) + + def test_split_1st_item_with_dot_and_two_spaces_before_space(self): + # Note: doesn't trim white spaces + self.setBlockText( + """ + 1. item 1 item 2 + """ + ) + self.setCaretTo(1, 11) + self.view.run_command("mde_number_list") + self.assertEqualBlockText( + """ + 1. item 1 + 2. item 2 + """ + ) + + def test_split_1st_item_with_dot_and_two_spaces_after_space(self): + # Note: doesn't trim white spaces + self.setBlockText( + """ + 1. item 1 item 2 + """ + ) + self.setCaretTo(1, 12) + self.view.run_command("mde_number_list") + self.assertEqualBlockText( + """ + 1. item 1\x20 + 2. item 2 + """ + ) + + def test_split_multiple_items_with_dot_and_one_space_before_space(self): + # Note: doesn't trim white spaces + self.setBlockText( + """ + 8. item 8 item 9 item 10 + """ + ) + self.setCaretTo(1, 10) + self.addCaretAt(1, 17) + self.view.run_command("mde_number_list") + self.assertEqualBlockText( + """ + 8. item 8 + 9. item 9 + 10. item 10 + """ + ) + + def test_split_multiple_items_with_dot_and_one_space_after_space(self): + # Note: doesn't trim white spaces + self.setBlockText( + """ + 8. item 8 item 9 item 10 + """ + ) + self.setCaretTo(1, 11) + self.addCaretAt(1, 18) + self.view.run_command("mde_number_list") + self.assertEqualBlockText( + """ + 8. item 8\x20 + 9. item 9\x20 + 10. item 10 + """ + ) + + def test_split_multiple_items_with_dot_and_two_space_before_space(self): + # Note: doesn't trim white spaces + # TODO: spaces after numbers need better treatment + self.setBlockText( + """ + 8. item 8 item 9 item 10 + """ + ) + self.setCaretTo(1, 11) + self.addCaretAt(1, 18) + self.view.run_command("mde_number_list") + self.assertEqualBlockText( + """ + 8. item 8 + 9. item 9 + 10. item 10 + """ + ) + + def test_split_multiple_items_with_dot_and_two_space_after_space(self): + # Note: doesn't trim white spaces + self.setBlockText( + """ + 8. item 8 item 9 item 10 + """ + ) + self.setCaretTo(1, 12) + self.addCaretAt(1, 19) + self.view.run_command("mde_number_list") + self.assertEqualBlockText( + """ + 8. item 8\x20 + 9. item 9\x20 + 10. item 10 + """ + ) + diff --git a/tests/test_toggle_tasks.py b/tests/test_toggle_tasks.py new file mode 100644 index 00000000..a0e67ad2 --- /dev/null +++ b/tests/test_toggle_tasks.py @@ -0,0 +1,426 @@ +from MarkdownEditing.tests import DereferrablePanelTestCase + + +class MdeToggleTaskListItemTestCase(DereferrablePanelTestCase): + + def test_set_task_with_asterisk_done_col1(self): + self._test_set_task_with_asterisk_done(1) + + def test_set_task_with_asterisk_done_col2(self): + self._test_set_task_with_asterisk_done(2) + + def test_set_task_with_asterisk_done_col4(self): + self._test_set_task_with_asterisk_done(4) + + def test_set_task_with_asterisk_done_col8(self): + self._test_set_task_with_asterisk_done(8) + + def test_set_task_with_asterisk_done_col12(self): + self._test_set_task_with_asterisk_done(12) + + def _test_set_task_with_asterisk_done(self, col): + self.setBlockText( + """ + * [ ] task 1 + """ + ) + self.setCaretTo(1, col) + self.view.run_command("mde_toggle_task_list_item") + self.assertEqualBlockText( + """ + * [X] task 1 + """ + ) + + def test_set_task_with_asterisk_undone_col1(self): + self._test_set_task_with_asterisk_undone(1) + + def test_set_task_with_asterisk_undone_col2(self): + self._test_set_task_with_asterisk_undone(2) + + def test_set_task_with_asterisk_undone_col4(self): + self._test_set_task_with_asterisk_undone(4) + + def test_set_task_with_asterisk_undone_col8(self): + self._test_set_task_with_asterisk_undone(8) + + def test_set_task_with_asterisk_undone_col12(self): + self._test_set_task_with_asterisk_undone(12) + + def _test_set_task_with_asterisk_undone(self, col): + self.setBlockText( + """ + * [X] task 1 + """ + ) + self.setCaretTo(1, col) + self.view.run_command("mde_toggle_task_list_item") + self.assertEqualBlockText( + """ + * [ ] task 1 + """ + ) + + def test_set_task_with_minus_done_col1(self): + self._test_set_task_with_minus_done(1) + + def test_set_task_with_minus_done_col2(self): + self._test_set_task_with_minus_done(2) + + def test_set_task_with_minus_done_col4(self): + self._test_set_task_with_minus_done(4) + + def test_set_task_with_minus_done_col8(self): + self._test_set_task_with_minus_done(8) + + def test_set_task_with_minus_done_col12(self): + self._test_set_task_with_minus_done(12) + + def _test_set_task_with_minus_done(self, col): + self.setBlockText( + """ + - [ ] task 1 + """ + ) + self.setCaretTo(1, col) + self.view.run_command("mde_toggle_task_list_item") + self.assertEqualBlockText( + """ + - [X] task 1 + """ + ) + + def test_set_task_with_minus_undone_col1(self): + self._test_set_task_with_minus_undone(1) + + def test_set_task_with_minus_undone_col2(self): + self._test_set_task_with_minus_undone(2) + + def test_set_task_with_minus_undone_col4(self): + self._test_set_task_with_minus_undone(4) + + def test_set_task_with_minus_undone_col8(self): + self._test_set_task_with_minus_undone(8) + + def test_set_task_with_minus_undone_col12(self): + self._test_set_task_with_minus_undone(12) + + def _test_set_task_with_minus_undone(self, col): + self.setBlockText( + """ + - [X] task 1 + """ + ) + self.setCaretTo(1, col) + self.view.run_command("mde_toggle_task_list_item") + self.assertEqualBlockText( + """ + - [ ] task 1 + """ + ) + + def test_set_task_with_plus_done_col1(self): + self._test_set_task_with_plus_done(1) + + def test_set_task_with_plus_done_col2(self): + self._test_set_task_with_plus_done(2) + + def test_set_task_with_plus_done_col4(self): + self._test_set_task_with_plus_done(4) + + def test_set_task_with_plus_done_col8(self): + self._test_set_task_with_plus_done(8) + + def test_set_task_with_plus_done_col12(self): + self._test_set_task_with_plus_done(12) + + def _test_set_task_with_plus_done(self, col): + self.setBlockText( + """ + + [ ] task 1 + """ + ) + self.setCaretTo(1, col) + self.view.run_command("mde_toggle_task_list_item") + self.assertEqualBlockText( + """ + + [X] task 1 + """ + ) + + def test_set_task_with_plus_undone_col1(self): + self._test_set_task_with_plus_undone(1) + + def test_set_task_with_plus_undone_col2(self): + self._test_set_task_with_plus_undone(2) + + def test_set_task_with_plus_undone_col4(self): + self._test_set_task_with_plus_undone(4) + + def test_set_task_with_plus_undone_col8(self): + self._test_set_task_with_plus_undone(8) + + def test_set_task_with_plus_undone_col12(self): + self._test_set_task_with_plus_undone(12) + + def _test_set_task_with_plus_undone(self, col): + self.setBlockText( + """ + + [X] task 1 + """ + ) + self.setCaretTo(1, col) + self.view.run_command("mde_toggle_task_list_item") + self.assertEqualBlockText( + """ + + [ ] task 1 + """ + ) + + def test_set_task_with_asterisk_in_quote_done_col1(self): + self._test_set_task_with_asterisk_in_quote_done(1) + + def test_set_task_with_asterisk_in_quote_done_col2(self): + self._test_set_task_with_asterisk_in_quote_done(2) + + def test_set_task_with_asterisk_in_quote_done_col4(self): + self._test_set_task_with_asterisk_in_quote_done(4) + + def test_set_task_with_asterisk_in_quote_done_col6(self): + self._test_set_task_with_asterisk_in_quote_done(6) + + def test_set_task_with_asterisk_in_quote_done_col12(self): + self._test_set_task_with_asterisk_in_quote_done(12) + + def _test_set_task_with_asterisk_in_quote_done(self, col): + self.setBlockText( + """ + > * [ ] task 1 + """ + ) + self.setCaretTo(1, col) + self.view.run_command("mde_toggle_task_list_item") + self.assertEqualBlockText( + """ + > * [X] task 1 + """ + ) + + def test_set_task_with_asterisk_in_quote_undone_col1(self): + self._test_set_task_with_asterisk_in_quote_undone(1) + + def test_set_task_with_asterisk_in_quote_undone_col2(self): + self._test_set_task_with_asterisk_in_quote_undone(2) + + def test_set_task_with_asterisk_in_quote_undone_col4(self): + self._test_set_task_with_asterisk_in_quote_undone(4) + + def test_set_task_with_asterisk_in_quote_undone_col6(self): + self._test_set_task_with_asterisk_in_quote_undone(6) + + def test_set_task_with_asterisk_in_quote_undone_col12(self): + self._test_set_task_with_asterisk_in_quote_undone(12) + + def _test_set_task_with_asterisk_in_quote_undone(self, col): + self.setBlockText( + """ + > * [X] task 1 + """ + ) + self.setCaretTo(1, col) + self.view.run_command("mde_toggle_task_list_item") + self.assertEqualBlockText( + """ + > * [ ] task 1 + """ + ) + + def test_set_task_with_minus_in_quote_done_col1(self): + self._test_set_task_with_minus_in_quote_done(1) + + def test_set_task_with_minus_in_quote_done_col2(self): + self._test_set_task_with_minus_in_quote_done(2) + + def test_set_task_with_minus_in_quote_done_col4(self): + self._test_set_task_with_minus_in_quote_done(4) + + def test_set_task_with_minus_in_quote_done_col6(self): + self._test_set_task_with_minus_in_quote_done(6) + + def test_set_task_with_minus_in_quote_done_col12(self): + self._test_set_task_with_minus_in_quote_done(12) + + def _test_set_task_with_minus_in_quote_done(self, col): + self.setBlockText( + """ + > - [ ] task 1 + """ + ) + self.setCaretTo(1, col) + self.view.run_command("mde_toggle_task_list_item") + self.assertEqualBlockText( + """ + > - [X] task 1 + """ + ) + + def test_set_task_with_minus_in_quote_undone_col1(self): + self._test_set_task_with_minus_in_quote_undone(1) + + def test_set_task_with_minus_in_quote_undone_col2(self): + self._test_set_task_with_minus_in_quote_undone(2) + + def test_set_task_with_minus_in_quote_undone_col4(self): + self._test_set_task_with_minus_in_quote_undone(4) + + def test_set_task_with_minus_in_quote_undone_col6(self): + self._test_set_task_with_minus_in_quote_undone(6) + + def test_set_task_with_minus_in_quote_undone_col12(self): + self._test_set_task_with_minus_in_quote_undone(12) + + def _test_set_task_with_minus_in_quote_undone(self, col): + self.setBlockText( + """ + > - [X] task 1 + """ + ) + self.setCaretTo(1, col) + self.view.run_command("mde_toggle_task_list_item") + self.assertEqualBlockText( + """ + > - [ ] task 1 + """ + ) + + def test_set_task_with_plus_in_quote_done_col1(self): + self._test_set_task_with_plus_in_quote_done(1) + + def test_set_task_with_plus_in_quote_done_col2(self): + self._test_set_task_with_plus_in_quote_done(2) + + def test_set_task_with_plus_in_quote_done_col4(self): + self._test_set_task_with_plus_in_quote_done(4) + + def test_set_task_with_plus_in_quote_done_col6(self): + self._test_set_task_with_plus_in_quote_done(6) + + def test_set_task_with_plus_in_quote_done_col12(self): + self._test_set_task_with_plus_in_quote_done(12) + + def _test_set_task_with_plus_in_quote_done(self, col): + self.setBlockText( + """ + > + [ ] task 1 + """ + ) + self.setCaretTo(1, col) + self.view.run_command("mde_toggle_task_list_item") + self.assertEqualBlockText( + """ + > + [X] task 1 + """ + ) + + def test_set_task_with_plus_in_quote_undone_col1(self): + self._test_set_task_with_plus_in_quote_undone(1) + + def test_set_task_with_plus_in_quote_undone_col2(self): + self._test_set_task_with_plus_in_quote_undone(2) + + def test_set_task_with_plus_in_quote_undone_col4(self): + self._test_set_task_with_plus_in_quote_undone(4) + + def test_set_task_with_plus_in_quote_undone_col6(self): + self._test_set_task_with_plus_in_quote_undone(6) + + def test_set_task_with_plus_in_quote_undone_col12(self): + self._test_set_task_with_plus_in_quote_undone(12) + + def _test_set_task_with_plus_in_quote_undone(self, col): + self.setBlockText( + """ + > + [X] task 1 + """ + ) + self.setCaretTo(1, col) + self.view.run_command("mde_toggle_task_list_item") + self.assertEqualBlockText( + """ + > + [ ] task 1 + """ + ) + + def test_toggle_multi_caret_tasks(self): + self.setBlockText( + """ + * [X] task 1 + - [X] sub task + + [X] sub task + * [ ] task 1 + - [ ] sub task + + [ ] sub task + > * [X] task 1 + > - [X] sub task + > + [X] sub task + > * [ ] task 1 + > - [ ] sub task + > + [ ] sub task + """ + ) + self.setCaretTo(1, 1) + for i in range(2, 13): + self.addCaretAt(i, 1) + self.view.run_command("mde_toggle_task_list_item") + self.assertEqualBlockText( + """ + * [ ] task 1 + - [ ] sub task + + [ ] sub task + * [X] task 1 + - [X] sub task + + [X] sub task + > * [ ] task 1 + > - [ ] sub task + > + [ ] sub task + > * [X] task 1 + > - [X] sub task + > + [X] sub task + """ + ) + + def test_toggle_selected_tasks(self): + self.setBlockText( + """ + * [X] task 1 + - [X] sub task + + [X] sub task + * [ ] task 1 + - [ ] sub task + + [ ] sub task + > * [X] task 1 + > - [X] sub task + > + [X] sub task + > * [ ] task 1 + > - [ ] sub task + > + [ ] sub task + """ + ) + self.view.run_command("select_all") + self.view.run_command("mde_toggle_task_list_item") + self.assertEqualBlockText( + """ + * [ ] task 1 + - [ ] sub task + + [ ] sub task + * [X] task 1 + - [X] sub task + + [X] sub task + > * [ ] task 1 + > - [ ] sub task + > + [ ] sub task + > * [X] task 1 + > - [X] sub task + > + [X] sub task + """ + ) diff --git a/unittesting.json b/unittesting.json new file mode 100644 index 00000000..bbcd0186 --- /dev/null +++ b/unittesting.json @@ -0,0 +1,14 @@ +{ + "tests_dir" : "tests", + "pattern" : "test*.py", + "async": false, + "deferred": true, + "verbosity": 1, + "capture_console": false, + "failfast": false, + "reload_package_on_testing": false, + "show_reload_progress": false, + "start_coverage_after_reload": false, + "output": null, + "generate_html_report": false +} diff --git a/wiki_page.py b/wiki_page.py deleted file mode 100644 index e95e99a8..00000000 --- a/wiki_page.py +++ /dev/null @@ -1,215 +0,0 @@ -import sublime, sublime_plugin -import os, string -import re - - -DEFAULT_MARKDOWN_EXTENSION = '.md' -PAGE_REF_FORMAT = '[[%s]]' -DEFAULT_HOME_PAGE = "HomePage" - - -class WikiPage: - def __init__(self, view): - self.view = view - - def identify_page_at_cursor(self): - for region in self.view.sel(): - text_on_cursor = None - - pos = region.begin() - scope_region = self.view.extract_scope(pos) - if not scope_region.empty(): - text_on_cursor = self.view.substr(scope_region) - return text_on_cursor.strip(string.punctuation) - - return None - - def select_page(self, pagename): - print("Open page: %s" % (pagename)) - - if pagename: - self.file_list = self.find_files_with_name(pagename) - - if len(self.file_list) > 1: - self.view.window().show_quick_panel(self.file_list, self.open_selected_file) - elif len(self.file_list) == 1: - self.open_selected_file(0) - else: - self.open_new_file(pagename) - - - def find_files_with_name(self, pagename): - pagename = pagename.replace('\\', os.sep).replace(os.sep+os.sep, os.sep).strip() - - self.current_file = self.view.file_name() - self.current_dir = os.path.dirname(self.current_file) - print("Locating page '%s' in: %s" % (pagename, self.current_dir) ) - - markdown_extension = self.view.settings().get("mde.wikilinks.markdown_extension", DEFAULT_MARKDOWN_EXTENSION) - - # Optionally strip extension... - if pagename.endswith(markdown_extension): - search_pattern = "^%s$" % pagename - else: - search_pattern = "^%s%s$" % (pagename, markdown_extension) - - # Scan directory tree for files that match the pagename... - results = [] - for dirname, _, files in self.list_dir_tree(self.current_dir): - for file in files: - if re.search(search_pattern, file): - filename = os.path.join(dirname, file) - results.append([self.extract_page_name(filename), filename]) - - return results - - def find_files_with_ref(self): - self.current_file = self.view.file_name() - self.current_dir, current_base = os.path.split(self.current_file) - self.current_name, _ = os.path.splitext(current_base) - - markdown_extension = self.view.settings().get("mde.wikilinks.markdown_extension", DEFAULT_MARKDOWN_EXTENSION) - - results = [] - for dirname, _, files in self.list_dir_tree(self.current_dir): - for file in files: - page_name, extension = os.path.splitext(file) - filename = os.path.join(dirname, file) - if extension == markdown_extension and self.contains_ref(filename, self.current_name): - results.append([page_name, filename]) - - return results - - - def contains_ref(self, filename, page_name): - link_text = PAGE_REF_FORMAT % page_name - - try: - if link_text in open(filename).read(): - return True - except: - pass - - return False - - - def select_backlink(self, file_list): - if file_list: - self.file_list = file_list - self.view.window().show_quick_panel(self.file_list, self.open_selected_file) - else: - msg = "No pages reference this page" - print(msg) - self.view.window().status_message(msg) - - - def open_new_file(self, pagename): - current_syntax = self.view.settings().get('syntax') - current_file = self.view.file_name() - current_dir = os.path.dirname(current_file) - - markdown_extension = self.view.settings().get("mde.wikilinks.markdown_extension", DEFAULT_MARKDOWN_EXTENSION) - - filename = os.path.join(current_dir, pagename + markdown_extension) - - new_view = self.view.window().new_file() - new_view.retarget(filename) - new_view.run_command('prepare_from_template', { - 'title': pagename, - 'template': 'default_page' - }) - print("Current syntax: %s" % current_syntax) - new_view.set_syntax_file(current_syntax) - - # Create but don't save page - # new_view.run_command('save') - - - def open_selected_file(self, selected_index): - if selected_index != -1: - _, file = self.file_list[selected_index] - - print("Opening file '%s'" % (file)) - self.view.window().open_file(file) - - def extract_page_name(self, filename): - _, base_name = os.path.split(filename) - page_name, _ = os.path.splitext(base_name) - - return page_name; - - - def list_dir_tree(self, directory): - for dir, dirnames, files in os.walk(directory): - dirnames[:] = [dirname for dirname in dirnames] - yield dir, dirnames, files - - def select_word_at_cursor(self): - word_region = None - - selection = self.view.sel() - for region in selection: - word_region = self.view.word(region) - if not word_region.empty(): - selection.clear() - selection.add(word_region) - return word_region - - return word_region - - def show_quick_list(self, file_list): - self.file_list = file_list - - window = self.view.window() - window.show_quick_panel(file_list, self.replace_selection_with_pagename) - - - def replace_selection_with_pagename(self, selected_index): - if selected_index != -1: - page_name, file = self.file_list[selected_index] - - print("Using selected page '%s'" % (page_name)) - self.view.run_command('replace_selected', {'text': page_name}) - - - def find_matching_files(self, word_region): - word = None if word_region.empty() else self.view.substr(word_region) - - current_file = self.view.file_name() - current_dir, current_base = os.path.split(current_file) - print("Finding matching files for %s in %s" % (word, current_dir)) - - markdown_extension = self.view.settings().get("mde.wikilinks.markdown_extension", DEFAULT_MARKDOWN_EXTENSION) - - # Optionally strip extension... - if word is not None and word.endswith(markdown_extension): - word = word[:-len(markdown_extension)] - - # Scan directory tree for potential filenames that contain the word... - results = [] - for dirname, _, files in self.list_dir_tree(current_dir): - for file in files: - page_name, extension = os.path.splitext(file) - filename = os.path.join(dirname, file) - - if extension == markdown_extension and (not word or word in page_name): - results.append([page_name, filename]) - - return results - - - def make_page_reference(self, edit, region): - print("Make page reference %s" % region) - - begin = region.begin() - end = region.end() - - self.view.insert(edit, end, "]]") - self.view.insert(edit, begin, "[[") - - if region.empty(): - region = sublime.Region(begin+2, end+2) - - selection = self.view.sel() - selection.clear() - selection.add(region)