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
|
||||
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_DIRS.append(STATICFILES_I18_TRG)
|
||||
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'),
|
||||
]
|
||||
|
||||
# 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 = [
|
||||
url(r'^api.js', DynamicJsView.as_view(template_name='js/api.js'), name='api.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'),
|
||||
url(r'^build.js', DynamicJsView.as_view(template_name='js/build.js'), name='build.js'),
|
||||
url(r'^calendar.js', DynamicJsView.as_view(template_name='js/calendar.js'), name='calendar.js'),
|
||||
url(r'^company.js', DynamicJsView.as_view(template_name='js/company.js'), name='company.js'),
|
||||
url(r'^filters.js', DynamicJsView.as_view(template_name='js/filters.js'), name='filters.js'),
|
||||
url(r'^forms.js', DynamicJsView.as_view(template_name='js/forms.js'), name='forms.js'),
|
||||
url(r'^inventree.js', DynamicJsView.as_view(template_name='js/inventree.js'), name='inventree.js'),
|
||||
url(r'^label.js', DynamicJsView.as_view(template_name='js/label.js'), name='label.js'),
|
||||
url(r'^model_renderers.js', DynamicJsView.as_view(template_name='js/model_renderers.js'), name='model_renderers.js'),
|
||||
url(r'^modals.js', DynamicJsView.as_view(template_name='js/modals.js'), name='modals.js'),
|
||||
url(r'^nav.js', DynamicJsView.as_view(template_name='js/nav.js'), name='nav.js'),
|
||||
url(r'^order.js', DynamicJsView.as_view(template_name='js/order.js'), name='order.js'),
|
||||
url(r'^part.js', DynamicJsView.as_view(template_name='js/part.js'), name='part.js'),
|
||||
url(r'^report.js', DynamicJsView.as_view(template_name='js/report.js'), name='report.js'),
|
||||
url(r'^stock.js', DynamicJsView.as_view(template_name='js/stock.js'), name='stock.js'),
|
||||
url(r'^tables.js', DynamicJsView.as_view(template_name='js/tables.js'), name='tables.js'),
|
||||
url(r'^table_filters.js', DynamicJsView.as_view(template_name='js/table_filters.js'), name='table_filters.js'),
|
||||
url(r'^inventree.js', DynamicJsView.as_view(template_name='js/dynamic/inventree.js'), name='inventree.js'),
|
||||
]
|
||||
|
||||
# These javascript files are pased through the Django translation layer
|
||||
translated_javascript_urls = [
|
||||
url(r'^api.js', DynamicJsView.as_view(template_name='js/translated/api.js'), name='api.js'),
|
||||
url(r'^attachment.js', DynamicJsView.as_view(template_name='js/translated/attachment.js'), name='attachment.js'),
|
||||
url(r'^barcode.js', DynamicJsView.as_view(template_name='js/translated/barcode.js'), name='barcode.js'),
|
||||
url(r'^bom.js', DynamicJsView.as_view(template_name='js/translated/bom.js'), name='bom.js'),
|
||||
url(r'^build.js', DynamicJsView.as_view(template_name='js/translated/build.js'), name='build.js'),
|
||||
url(r'^calendar.js', DynamicJsView.as_view(template_name='js/translated/calendar.js'), name='calendar.js'),
|
||||
url(r'^company.js', DynamicJsView.as_view(template_name='js/translated/company.js'), name='company.js'),
|
||||
url(r'^filters.js', DynamicJsView.as_view(template_name='js/translated/filters.js'), name='filters.js'),
|
||||
url(r'^forms.js', DynamicJsView.as_view(template_name='js/translated/forms.js'), name='forms.js'),
|
||||
url(r'^label.js', DynamicJsView.as_view(template_name='js/translated/label.js'), name='label.js'),
|
||||
url(r'^model_renderers.js', DynamicJsView.as_view(template_name='js/translated/model_renderers.js'), name='model_renderers.js'),
|
||||
url(r'^modals.js', DynamicJsView.as_view(template_name='js/translated/modals.js'), name='modals.js'),
|
||||
url(r'^nav.js', DynamicJsView.as_view(template_name='js/translated/nav.js'), name='nav.js'),
|
||||
url(r'^order.js', DynamicJsView.as_view(template_name='js/translated/order.js'), name='order.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 = [
|
||||
@ -123,7 +127,8 @@ urlpatterns = [
|
||||
url(r'^supplier-part/', include(supplier_part_urls)),
|
||||
|
||||
# "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)),
|
||||
|
||||
|
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