diff --git a/mkdocs/nav.py b/mkdocs/nav.py index b73879d5..7240ef22 100644 --- a/mkdocs/nav.py +++ b/mkdocs/nav.py @@ -248,7 +248,7 @@ class Page(object): 'page_read_source', None, config=config, page=self) if source is None: try: - with io.open(self.abs_input_path, 'r', encoding='utf-8') as f: + with io.open(self.abs_input_path, 'r', encoding='utf-8-sig') as f: source = f.read() except IOError: log.error('File not found: %s', self.abs_input_path) diff --git a/mkdocs/tests/build_tests.py b/mkdocs/tests/build_tests.py index 4820e92d..ac5f5116 100644 --- a/mkdocs/tests/build_tests.py +++ b/mkdocs/tests/build_tests.py @@ -7,6 +7,7 @@ import shutil import tempfile import unittest import mock +import io try: from itertools import izip as zip @@ -464,3 +465,32 @@ class BuildTests(unittest.TestCase): context = build.get_context(mock.Mock(), cfg) self.assertEqual(context['config']['extra']['a'], 1) + + def test_BOM(self): + docs_dir = tempfile.mkdtemp() + site_dir = tempfile.mkdtemp() + try: + # Create an UTF-8 Encoded file with BOM (as Micorsoft editors do). See #1186. + f = io.open(os.path.join(docs_dir, 'index.md'), 'w', encoding='utf-8-sig') + f.write('# An UTF-8 encoded file with a BOM') + f.close() + + cfg = load_config( + docs_dir=docs_dir, + site_dir=site_dir + ) + build.build(cfg) + + # Verify that the file was generated properly. + # If the BOM is not removed, Markdown will return: + # `
\ufeff# An UTF-8 encoded file with a BOM
`. + f = io.open(os.path.join(site_dir, 'index.html'), 'r', encoding='utf-8') + output = f.read() + f.close() + self.assertTrue( + '