mirror of
https://github.com/inventree/InvenTree
synced 2024-08-30 18:33:04 +00:00
Split dynamic javascript files into two separate directories
- One gets translated and is served statically - One does not get translated and is served dynamically - Add CI step
This commit is contained in:
parent
bc3c3be751
commit
14aebfdae1
28
.github/workflows/javascript.yaml
vendored
Normal file
28
.github/workflows/javascript.yaml
vendored
Normal file
@ -0,0 +1,28 @@
|
|||||||
|
# Check javascript template files
|
||||||
|
|
||||||
|
name: Javascript Templates
|
||||||
|
|
||||||
|
on:
|
||||||
|
push:
|
||||||
|
branches:
|
||||||
|
- master
|
||||||
|
|
||||||
|
pull_request:
|
||||||
|
branches-ignore:
|
||||||
|
- l10*
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
|
||||||
|
python:
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
|
||||||
|
env:
|
||||||
|
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||||
|
steps:
|
||||||
|
- name: Checkout Code
|
||||||
|
uses: actions/checkout@v2
|
||||||
|
- name: Check Files
|
||||||
|
run: |
|
||||||
|
cd ci
|
||||||
|
python check_js_templates.py
|
||||||
|
|
@ -202,7 +202,7 @@ STATICFILES_DIRS = [
|
|||||||
|
|
||||||
# Translated Template settings
|
# Translated Template settings
|
||||||
STATICFILES_I18_PREFIX = 'i18n'
|
STATICFILES_I18_PREFIX = 'i18n'
|
||||||
STATICFILES_I18_SRC = os.path.join(BASE_DIR, 'templates', 'js')
|
STATICFILES_I18_SRC = os.path.join(BASE_DIR, 'templates', 'js', 'translated')
|
||||||
STATICFILES_I18_TRG = STATICFILES_DIRS[0] + '_' + STATICFILES_I18_PREFIX
|
STATICFILES_I18_TRG = STATICFILES_DIRS[0] + '_' + STATICFILES_I18_PREFIX
|
||||||
STATICFILES_DIRS.append(STATICFILES_I18_TRG)
|
STATICFILES_DIRS.append(STATICFILES_I18_TRG)
|
||||||
STATICFILES_I18_TRG = os.path.join(STATICFILES_I18_TRG, STATICFILES_I18_PREFIX)
|
STATICFILES_I18_TRG = os.path.join(STATICFILES_I18_TRG, STATICFILES_I18_PREFIX)
|
||||||
|
@ -93,28 +93,32 @@ settings_urls = [
|
|||||||
url(r'^.*$', SettingsView.as_view(template_name='InvenTree/settings/settings.html'), name='settings'),
|
url(r'^.*$', SettingsView.as_view(template_name='InvenTree/settings/settings.html'), name='settings'),
|
||||||
]
|
]
|
||||||
|
|
||||||
# Some javascript files are served 'dynamically', allowing them to pass through the Django translation layer
|
# These javascript files are served "dynamically" - i.e. rendered on demand
|
||||||
dynamic_javascript_urls = [
|
dynamic_javascript_urls = [
|
||||||
url(r'^api.js', DynamicJsView.as_view(template_name='js/api.js'), name='api.js'),
|
url(r'^inventree.js', DynamicJsView.as_view(template_name='js/dynamic/inventree.js'), name='inventree.js'),
|
||||||
url(r'^attachment.js', DynamicJsView.as_view(template_name='js/attachment.js'), name='attachment.js'),
|
]
|
||||||
url(r'^barcode.js', DynamicJsView.as_view(template_name='js/barcode.js'), name='barcode.js'),
|
|
||||||
url(r'^bom.js', DynamicJsView.as_view(template_name='js/bom.js'), name='bom.js'),
|
# These javascript files are pased through the Django translation layer
|
||||||
url(r'^build.js', DynamicJsView.as_view(template_name='js/build.js'), name='build.js'),
|
translated_javascript_urls = [
|
||||||
url(r'^calendar.js', DynamicJsView.as_view(template_name='js/calendar.js'), name='calendar.js'),
|
url(r'^api.js', DynamicJsView.as_view(template_name='js/translated/api.js'), name='api.js'),
|
||||||
url(r'^company.js', DynamicJsView.as_view(template_name='js/company.js'), name='company.js'),
|
url(r'^attachment.js', DynamicJsView.as_view(template_name='js/translated/attachment.js'), name='attachment.js'),
|
||||||
url(r'^filters.js', DynamicJsView.as_view(template_name='js/filters.js'), name='filters.js'),
|
url(r'^barcode.js', DynamicJsView.as_view(template_name='js/translated/barcode.js'), name='barcode.js'),
|
||||||
url(r'^forms.js', DynamicJsView.as_view(template_name='js/forms.js'), name='forms.js'),
|
url(r'^bom.js', DynamicJsView.as_view(template_name='js/translated/bom.js'), name='bom.js'),
|
||||||
url(r'^inventree.js', DynamicJsView.as_view(template_name='js/inventree.js'), name='inventree.js'),
|
url(r'^build.js', DynamicJsView.as_view(template_name='js/translated/build.js'), name='build.js'),
|
||||||
url(r'^label.js', DynamicJsView.as_view(template_name='js/label.js'), name='label.js'),
|
url(r'^calendar.js', DynamicJsView.as_view(template_name='js/translated/calendar.js'), name='calendar.js'),
|
||||||
url(r'^model_renderers.js', DynamicJsView.as_view(template_name='js/model_renderers.js'), name='model_renderers.js'),
|
url(r'^company.js', DynamicJsView.as_view(template_name='js/translated/company.js'), name='company.js'),
|
||||||
url(r'^modals.js', DynamicJsView.as_view(template_name='js/modals.js'), name='modals.js'),
|
url(r'^filters.js', DynamicJsView.as_view(template_name='js/translated/filters.js'), name='filters.js'),
|
||||||
url(r'^nav.js', DynamicJsView.as_view(template_name='js/nav.js'), name='nav.js'),
|
url(r'^forms.js', DynamicJsView.as_view(template_name='js/translated/forms.js'), name='forms.js'),
|
||||||
url(r'^order.js', DynamicJsView.as_view(template_name='js/order.js'), name='order.js'),
|
url(r'^label.js', DynamicJsView.as_view(template_name='js/translated/label.js'), name='label.js'),
|
||||||
url(r'^part.js', DynamicJsView.as_view(template_name='js/part.js'), name='part.js'),
|
url(r'^model_renderers.js', DynamicJsView.as_view(template_name='js/translated/model_renderers.js'), name='model_renderers.js'),
|
||||||
url(r'^report.js', DynamicJsView.as_view(template_name='js/report.js'), name='report.js'),
|
url(r'^modals.js', DynamicJsView.as_view(template_name='js/translated/modals.js'), name='modals.js'),
|
||||||
url(r'^stock.js', DynamicJsView.as_view(template_name='js/stock.js'), name='stock.js'),
|
url(r'^nav.js', DynamicJsView.as_view(template_name='js/translated/nav.js'), name='nav.js'),
|
||||||
url(r'^tables.js', DynamicJsView.as_view(template_name='js/tables.js'), name='tables.js'),
|
url(r'^order.js', DynamicJsView.as_view(template_name='js/translated/order.js'), name='order.js'),
|
||||||
url(r'^table_filters.js', DynamicJsView.as_view(template_name='js/table_filters.js'), name='table_filters.js'),
|
url(r'^part.js', DynamicJsView.as_view(template_name='js/translated/part.js'), name='part.js'),
|
||||||
|
url(r'^report.js', DynamicJsView.as_view(template_name='js/translated/report.js'), name='report.js'),
|
||||||
|
url(r'^stock.js', DynamicJsView.as_view(template_name='js/translated/stock.js'), name='stock.js'),
|
||||||
|
url(r'^tables.js', DynamicJsView.as_view(template_name='js/translated/tables.js'), name='tables.js'),
|
||||||
|
url(r'^table_filters.js', DynamicJsView.as_view(template_name='js/translated/table_filters.js'), name='table_filters.js'),
|
||||||
]
|
]
|
||||||
|
|
||||||
urlpatterns = [
|
urlpatterns = [
|
||||||
@ -123,7 +127,8 @@ urlpatterns = [
|
|||||||
url(r'^supplier-part/', include(supplier_part_urls)),
|
url(r'^supplier-part/', include(supplier_part_urls)),
|
||||||
|
|
||||||
# "Dynamic" javascript files which are rendered using InvenTree templating.
|
# "Dynamic" javascript files which are rendered using InvenTree templating.
|
||||||
url(r'^dynamic/', include(dynamic_javascript_urls)),
|
url(r'^js/dynamic/', include(dynamic_javascript_urls)),
|
||||||
|
url(r'^js/i18n/', include(translated_javascript_urls)),
|
||||||
|
|
||||||
url(r'^common/', include(common_urls)),
|
url(r'^common/', include(common_urls)),
|
||||||
|
|
||||||
|
121
ci/check_js_templates.py
Normal file
121
ci/check_js_templates.py
Normal file
@ -0,0 +1,121 @@
|
|||||||
|
"""
|
||||||
|
Test that the "translated" javascript files to not contain template tags
|
||||||
|
which need to be determined at "run time".
|
||||||
|
|
||||||
|
This is because the "translated" javascript files are compiled into the "static" directory.
|
||||||
|
|
||||||
|
They should only contain template tags that render static information.
|
||||||
|
"""
|
||||||
|
|
||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
from __future__ import unicode_literals
|
||||||
|
|
||||||
|
import sys
|
||||||
|
import re
|
||||||
|
import os
|
||||||
|
import pathlib
|
||||||
|
|
||||||
|
here = os.path.abspath(os.path.dirname(__file__))
|
||||||
|
template_dir = os.path.abspath(os.path.join(here, '..', 'InvenTree', 'templates'))
|
||||||
|
|
||||||
|
# We only care about the 'translated' files
|
||||||
|
js_i18n_dir = os.path.join(template_dir, 'js', 'translated')
|
||||||
|
js_dynamic_dir = os.path.join(template_dir, 'js', 'dynamic')
|
||||||
|
|
||||||
|
errors = 0
|
||||||
|
|
||||||
|
print("=================================")
|
||||||
|
print("Checking static javascript files:")
|
||||||
|
print("=================================")
|
||||||
|
|
||||||
|
def check_invalid_tag(data):
|
||||||
|
|
||||||
|
pattern = r"{%(\w+)"
|
||||||
|
|
||||||
|
err_count = 0
|
||||||
|
|
||||||
|
for idx, line in enumerate(data):
|
||||||
|
|
||||||
|
results = re.findall(pattern, line)
|
||||||
|
|
||||||
|
for result in results:
|
||||||
|
err_count += 1
|
||||||
|
|
||||||
|
print(f" - Error on line {idx+1}: %{{{result[0]}")
|
||||||
|
|
||||||
|
return err_count
|
||||||
|
|
||||||
|
def check_prohibited_tags(data):
|
||||||
|
|
||||||
|
allowed_tags = [
|
||||||
|
'if',
|
||||||
|
'elif',
|
||||||
|
'else',
|
||||||
|
'endif',
|
||||||
|
'for',
|
||||||
|
'endfor',
|
||||||
|
'trans',
|
||||||
|
'load',
|
||||||
|
'include',
|
||||||
|
'url',
|
||||||
|
]
|
||||||
|
|
||||||
|
pattern = r"{% (\w+)\s"
|
||||||
|
|
||||||
|
err_count = 0
|
||||||
|
|
||||||
|
has_trans = False
|
||||||
|
|
||||||
|
for idx, line in enumerate(data):
|
||||||
|
|
||||||
|
for tag in re.findall(pattern, line):
|
||||||
|
|
||||||
|
if tag not in allowed_tags:
|
||||||
|
print(f" > Line {idx+1} - '{tag}'")
|
||||||
|
err_count += 1
|
||||||
|
|
||||||
|
if tag == 'trans':
|
||||||
|
has_trans = True
|
||||||
|
|
||||||
|
if not has_trans:
|
||||||
|
print(f" > missing 'trans' tag")
|
||||||
|
err_count += 1
|
||||||
|
|
||||||
|
return err_count
|
||||||
|
|
||||||
|
|
||||||
|
for filename in pathlib.Path(js_i18n_dir).rglob('*.js'):
|
||||||
|
|
||||||
|
print(f"Checking file 'translated/{os.path.basename(filename)}':")
|
||||||
|
|
||||||
|
with open(filename, 'r') as js_file:
|
||||||
|
data = js_file.readlines()
|
||||||
|
|
||||||
|
errors += check_invalid_tag(data)
|
||||||
|
errors += check_prohibited_tags(data)
|
||||||
|
|
||||||
|
for filename in pathlib.Path(js_dynamic_dir).rglob('*.js'):
|
||||||
|
|
||||||
|
print(f"Checking file 'dynamic/{os.path.basename(filename)}':")
|
||||||
|
|
||||||
|
# Check that the 'dynamic' files do not contains any translated strings
|
||||||
|
with open(filename, 'r') as js_file:
|
||||||
|
data = js_file.readlines()
|
||||||
|
|
||||||
|
pattern = r'{% trans '
|
||||||
|
|
||||||
|
err_count = 0
|
||||||
|
|
||||||
|
for idx, line in enumerate(data):
|
||||||
|
|
||||||
|
results = re.findall(pattern, line)
|
||||||
|
|
||||||
|
if len(results) > 0:
|
||||||
|
errors += 1
|
||||||
|
|
||||||
|
print(f" > {{% trans %}} tag found at line {idx + 1}")
|
||||||
|
|
||||||
|
if errors > 0:
|
||||||
|
print(f"Found {errors} incorrect template tags")
|
||||||
|
|
||||||
|
sys.exit(errors)
|
Loading…
Reference in New Issue
Block a user