diff --git a/Makefile b/Makefile index 76cab58..e017978 100644 --- a/Makefile +++ b/Makefile @@ -17,13 +17,9 @@ sm_docset := sublime-merge.docset sm_built_path := $(sm_site)/$(sm_docset) .PHONY: all -all: clean pre-build build +all: clean pre-build build post-build test -.PHONY: fix -pre-build: fix-html - -.PHONY: fix-html -fix-html: +pre-build: python fix_html.py build: @@ -38,6 +34,9 @@ build: cd $(sm_site) && dashing build mv $(sm_built_path) $(out_folder) +post-build: + python fix_index.py + .PHONY: clean clean: [ -d "$(out_folder)" ] && rm -r $(out_folder) || true @@ -49,5 +48,9 @@ zip: cd $(out_folder) && tar -czvf $(st_docset).tgz $(st_docset) cd $(out_folder) && tar -czvf $(sm_docset).tgz $(sm_docset) +.PHONY: test +test: + cd test && python -m unittest + install-linux: cp -r $(out_folder)/* $(install_path_linux) diff --git a/fix_index.py b/fix_index.py new file mode 100644 index 0000000..c2de483 --- /dev/null +++ b/fix_index.py @@ -0,0 +1,53 @@ +#!/usr/bin/env python3 + +""" +Tweaks the docset SQLite index after creation +""" +import sys +import sqlite3 + +SQLITE_PATH_FMT = 'out/{}/Contents/Resources/docSet.dsidx' +DOCSET_FIXES = { + 'sublime-text.docset': [ + ('docs/distraction_free.html', + 'Packages/Default/Distraction\nFree.sublime-settings', + 'Packages/Default/Distraction Free.sublime-settings',), + ('docs/distraction_free.html', + 'Packages/User/Distraction\nFree.sublime-settings', + 'Packages/User/Distraction Free.sublime-settings',), + ('docs/syntax.html', + ' SYNTAX\nTEST ""', + ' SYNTAX TEST ""', ), + ], + 'sublime-merge.docset': [] +} + + +def main(): + for docset in DOCSET_FIXES: + con = sqlite3.connect(SQLITE_PATH_FMT.format(docset)) + cur = con.cursor() + + for fix in DOCSET_FIXES[docset]: + path, old_name, new_name = fix + data = { + 'old_name': old_name, + 'new_name': new_name, + 'path_like': path + '#%', + } + + cur.execute( + ''' + UPDATE searchIndex + SET name = :new_name + WHERE name = :old_name + AND path LIKE :path_like + ''', + data + ) + con.commit() + con.close() + + +if __name__ == '__main__': + sys.exit(main()) diff --git a/sublime-text-dashing.yml b/sublime-text-dashing.yml index 52bb0c5..b4ece23 100644 --- a/sublime-text-dashing.yml +++ b/sublime-text-dashing.yml @@ -31,7 +31,7 @@ selectors: # Git Status badges '#status-badge-key .badges li': - type: Enum + type: Attribute matchpath: '/git_integration\.html$' # Commands and menus diff --git a/test/test_docset.py b/test/test_docset.py new file mode 100644 index 0000000..beff2bb --- /dev/null +++ b/test/test_docset.py @@ -0,0 +1,119 @@ +import unittest +import sqlite3 + +from abc import ABC +from collections import defaultdict + + +class DocsetTestCaseBase(ABC, unittest.TestCase): + NAME = None + SQLITE_PATH_FMT = '../out/{}/Contents/Resources/docSet.dsidx' + + @classmethod + def setUpClass(cls): + cls.con = sqlite3.connect(cls.SQLITE_PATH_FMT.format(cls.NAME)) + cls.cur = cls.con.cursor() + + @classmethod + def tearDownClass(cls): + cls.con.close() + + def test_no_empty_aliases(self): + """The docset index must not contain empty entries""" + sql = ''' + SELECT * + FROM searchIndex + WHERE name = '' + ''' + res = self.cur.execute(sql) + self.assertFalse(res.fetchall()) + + def test_no_newline_aliases(self): + """The docset index must not contain entries with newlines in them""" + sql = ''' + SELECT * + FROM searchIndex + WHERE name LIKE '%\n%' + ''' + res = self.cur.execute(sql) + self.assertFalse(res.fetchall()) + + @unittest.skip('Not implemented') + def test_no_broken_paths(self): + """The docset index must not contain broken paths""" + pass + + def test_paths_are_autolinks(self): + """Sanity check dashing format""" + sql = ''' + SELECT * + FROM searchIndex + WHERE path NOT LIKE 'docs/%.html#autolink-%' + ''' + res = self.cur.execute(sql) + self.assertFalse(res.fetchall()) + + def _test_a_doc_page_index( + self, path: str, + contains_strict: list[tuple[str,str]], + contains_lenient: list[tuple[str,str]] | None = None, + ): + sql = f''' + SELECT type, name + FROM searchIndex + WHERE path LIKE '{path}#%' + ''' + res = self.cur.execute(sql) + items = res.fetchall() + + for pair in contains_lenient or []: + self.assertIn(pair, items) + + lookup = defaultdict(list) + for check in contains_strict: + lookup[check[1]].append(check[0]) + + for pair in contains_strict: + self.assertIn(pair, items) + + ds_type, ds_term = pair + lookup_result = lookup[ds_term][:] + self.assertFalse(lookup_result.remove(ds_type)) + + +class SublimeMergeDocsetTestCase(DocsetTestCaseBase): + NAME = 'sublime-merge.docset' + + +class SublimeTextDocsetTestCase(DocsetTestCaseBase): + NAME = 'sublime-text.docset' + + def test_git_integration(self): + contains = [ + ('Guide', 'Git Integration'), + ('Attribute', 'Staged Modification'), + ('Section', 'Diff Markers'), + ('Command', 'Open Git Repository…'), + ('Command', 'Sublime Merge: Folder History'), + ] + self._test_a_doc_page_index('docs/git_integration.html', contains) + + def test_api_reference(self): + contains = [ + ('Guide', 'API Reference'), + ('Module', 'sublime'), + ('Module', 'sublime_plugin'), + ('Class', 'sublime.Window'), + ('Type', 'sublime.Kind'), + ('Type', 'sublime.Event'), + ('Class', 'sublime_plugin.EventListener'), + ('Method', 'sublime_plugin.ViewEventListener.on_activated'), + ('Function', 'sublime.cache_path'), + ('Attribute', 'sublime.KindId.COLOR_YELLOWISH'), + ('Attribute', 'sublime.RegionFlags.DRAW_EMPTY_AS_OVERWRITE'), + ] + self._test_a_doc_page_index('docs/api_reference.html', contains) + + +# Don't test the base class directly +del DocsetTestCaseBase