Skip to content

Serve CodeMirror CSS and JS locally. #10

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 1 commit into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
45 changes: 30 additions & 15 deletions flask_codemirror/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -23,10 +23,11 @@
for Flask
"""

import os
import requests
import warnings
from jinja2 import Markup
from flask import current_app
from flask import current_app, url_for
try:
from urllib.parse import urljoin
except ImportError:
Expand All @@ -50,7 +51,9 @@ class CodeMirrorHeaders(object):
THEME_KEY = 'CODEMIRROR_THEME'
ADDONS_KEY = 'CODEMIRROR_ADDONS'
VERSION_KEY = 'CODEMIRROR_VERSION'
SERVE_LOCAL_KEY = 'CODEMIRROR_SERVE_LOCAL'
CDN_URL = '//cdnjs.cloudflare.com/ajax/libs/codemirror/{0}/'
LOCAL_PATH = '/codemirror/{0}'
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think it should be better if there was a config key for this path, since it's local users could host the scripts where they want.

LANGUAGE_REL_URL = 'mode/{0}/{0}.js'
THEME_REL_URL = 'theme/{0}.css'
ADDON_REL_URL = 'addon/{0}/{1}.js'
Expand All @@ -62,8 +65,12 @@ def __init__(self, config):
self.languages = config.get(self.__class__.LANGUAGES_KEY, [])
self.addons = config.get(self.__class__.ADDONS_KEY, None)
self.version = config.get(self.__class__.VERSION_KEY, '4.12.0')
self.serve_local = config.get(self.__class__.SERVE_LOCAL_KEY, False)
# construct base url
self.base_url = self.__class__.CDN_URL.format(self.version)
if self.serve_local:
self.base_url = None
else:
self.base_url = self.__class__.CDN_URL.format(self.version)
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Not mandatory since you check self.serve_local later

if not self.languages:
error = '{0} is required'.format(self.__class__.LANGUAGES_KEY)
raise CodeMirrorConfigException(error)
Expand All @@ -75,19 +82,27 @@ def _get_tag(self, url, tag, print_warn=True):
:param print_warn: if True print warn when url is unavailable
"""
# construct complete url
complete_url = urljoin(self.base_url, url)
# check if exists
if requests.get('http:' + complete_url).ok:
# construct tag
if tag == 'script':
return '<script src="{0}"></script>'.format(complete_url)
elif tag == 'stylesheet':
return '<link rel="stylesheet" href="{0}">'.format(complete_url)
else:
warnings.warn('Given tag is not valid')
elif print_warn:
warnings.warn('Url {0} not valid'.format(complete_url))
return None
if self.serve_local:
complete_url = url_for(
'static',
filename=os.path.join(self.__class__.LOCAL_PATH.format(self.version), url).lstrip('/')
)
else:
complete_url = urljoin(self.base_url, url)
# check if exists
if not requests.get('http:' + complete_url).ok:
if print_warn:
warnings.warn('Url {0} not valid'.format(complete_url))
return None

# construct tag
if tag == 'script':
return '<script src="{0}"></script>'.format(complete_url)
elif tag == 'stylesheet':
return '<link rel="stylesheet" href="{0}">'.format(complete_url)
else:
warnings.warn('Given tag is not valid')
return None

def include_codemirror(self):
"""Include resources in pages"""
Expand Down
2 changes: 1 addition & 1 deletion setup.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
"""
from setuptools import setup

__version__ = '1.0'
__version__ = '1.1'
__author__ = 'TROUVERIE Joachim'
__contact__ = '[email protected]'

Expand Down
109 changes: 80 additions & 29 deletions test.py
Original file line number Diff line number Diff line change
Expand Up @@ -31,44 +31,53 @@

__author__ = 'TROUVERIE Joachim'

# create app
app = Flask(__name__)
def make_app(more_config=None):
# create app
app = Flask(__name__)

# config
CODEMIRROR_LANGUAGES = ['python']
CODEMIRROR_THEME = '3024-day'
CODEMIRROR_ADDONS = (('dialog', 'dialog'), ('mode', 'overlay'))
CODEMIRROR_VERSION = '4.12.0'
SECRET_KEY = 'secret!'
app.config.from_object(__name__)
# config
app.config.update({
'TESTING': True,
'CODEMIRROR_LANGUAGES': ['python'],
'CODEMIRROR_THEME': '3024-day',
'CODEMIRROR_ADDONS': (('dialog', 'dialog'), ('mode', 'overlay')),
'CODEMIRROR_VERSION': '4.12.0',
'SECRET_KEY': 'secret!',
})
if more_config:
app.config.update(more_config)

# codemirror
codemirror = CodeMirror(app)
# codemirror
codemirror = CodeMirror(app)


class MyForm(Form):
code = CodeMirrorField(language='python', id='test',
config={'linenumbers': True})
class MyForm(Form):
code = CodeMirrorField(language='python', id='test',
config={'linenumbers': True})


@app.route('/')
def index():
return render_template_string('{{ codemirror.include_codemirror() }}')
@app.route('/')
def index():
return render_template_string('{{ codemirror.include_codemirror() }}')


@app.route('/form/')
def form():
test_form = MyForm()
return render_template_string('{{ form.code }}', form=test_form)
@app.route('/form/')
def form():
test_form = MyForm()
return render_template_string('{{ form.code }}', form=test_form)

return app


class FlaskCodeMirrorTestBase(unittest.TestCase):
def setUp(self, more_config=None):
self.app = make_app(more_config)
self.app_client = self.app.test_client()

class FlaskCodeMirrorTest(unittest.TestCase):
def setUp(self):
app.config['TESTING'] = True
self.app = app.test_client()

class FlaskCodeMirrorTestHead(FlaskCodeMirrorTestBase):
def test_head(self):
response = self.app.get('/')
response = self.app_client.get('/')
self.assertIn(
'<script src="//cdnjs.cloudflare.com/ajax/libs/codemirror/4.12.0/codemirror.js"></script>',
response.data
Expand Down Expand Up @@ -106,8 +115,9 @@ def test_head(self):
response.data
)

class FlaskCodeMirrorTestForm(FlaskCodeMirrorTestBase):
def test_form(self):
response = self.app.get('/form/')
response = self.app_client.get('/form/')
self.assertIn(
'<textarea id="flask-codemirror-test" name="code">',
response.data
Expand All @@ -125,10 +135,51 @@ def test_form(self):
response.data
)

class FlaskCodeMirrorTestExc(unittest.TestCase):
def test_exception(self):
app.config['CODEMIRROR_LANGUAGES'] = None
with self.assertRaises(CodeMirrorConfigException):
CodeMirror(app)
app = make_app({'CODEMIRROR_LANGUAGES': None})


class FlaskCodeMirrorTestLocal(FlaskCodeMirrorTestBase):
def setUp(self):
super(FlaskCodeMirrorTestLocal, self).setUp({'CODEMIRROR_SERVE_LOCAL': True})

def test_head(self):
response = self.app_client.get('/')
self.assertIn(
'<script src="/static/codemirror/4.12.0/codemirror.js"></script>',
response.data
)
self.assertIn(
'<link rel="stylesheet" href="/static/codemirror/4.12.0/codemirror.css">',
response.data
)
self.assertIn(
'<script src="/static/codemirror/4.12.0/mode/python/python.js"></script>',
response.data
)
self.assertIn(
'<link rel="stylesheet" href="/static/codemirror/4.12.0/theme/3024-day.css">',
response.data
)
self.assertIn(
'<link rel="stylesheet" href="/static/codemirror/4.12.0/theme/3024-day.css">',
response.data
)
self.assertIn(
'<link rel="stylesheet" href="/static/codemirror/4.12.0/addon/dialog/dialog.css">',
response.data
)
self.assertIn(
'<script src="/static/codemirror/4.12.0/addon/dialog/dialog.js"></script>',
response.data
)
self.assertIn(
'<script src="/static/codemirror/4.12.0/addon/mode/overlay.js"></script>',
response.data
)


if __name__ == '__main__':
unittest.main()