From f96c0d4f819cc800b15efcc11d4d01407234d3a9 Mon Sep 17 00:00:00 2001 From: David Avs Date: Wed, 25 Nov 2015 07:15:12 -0500 Subject: [PATCH 1/3] Basic dumb index page --- rest_admin/sites.py | 28 +++++- .../templates/rest_admin/base_site.html | 9 ++ rest_admin/templates/rest_admin/index.html | 87 +++++++++++++++++++ rest_admin/views.py | 6 ++ 4 files changed, 128 insertions(+), 2 deletions(-) create mode 100644 rest_admin/templates/rest_admin/base_site.html create mode 100644 rest_admin/templates/rest_admin/index.html diff --git a/rest_admin/sites.py b/rest_admin/sites.py index 69268f0..12af565 100644 --- a/rest_admin/sites.py +++ b/rest_admin/sites.py @@ -87,7 +87,7 @@ def get_apps(self, request): return sorted(filter(lambda itm: itm.models, app_dict.values()), key=lambda itm: itm.name) - def get_urls(self): + def get_api_urls(self): from django.conf.urls import url from .views import AdminAppsView # # Since this module gets imported in the application's root package, @@ -137,9 +137,33 @@ def get_urls(self): return urlpatterns + def get_view_urls(self): + from django.conf.urls import url + from .views import AdminIndexView + return [ + url('^', AdminIndexView.as_view(), name='index'), + ] + + @property + def api_urls(self): + from django.conf.urls import url, include + urlpatterns = [url('^', include(self.get_api_urls(), namespace='api'))] + return (urlpatterns, 'rest_admin', self.name) + + @property + def view_urls(self): + from django.conf.urls import url, include + urlpatterns = [url('^', include(self.get_view_urls(), namespace='view'))] + return (urlpatterns, 'rest_admin', self.name) + @property def urls(self): - return self.get_urls(), 'admin', self.name + from django.conf.urls import url, include + urlpatterns = [ + url('^api/', include(self.get_api_urls(), namespace='api')), + url('^', include(self.get_view_urls(), namespace='view')), + ] + return (urlpatterns, 'rest_admin', self.name) # To be consistent with Django admin (see `django.contrib.admin.sites`). diff --git a/rest_admin/templates/rest_admin/base_site.html b/rest_admin/templates/rest_admin/base_site.html new file mode 100644 index 0000000..46a271a --- /dev/null +++ b/rest_admin/templates/rest_admin/base_site.html @@ -0,0 +1,9 @@ +{% extends "admin/base.html" %} + +{% block title %}{{ title }} | {{ site_title|default:_('Django site admin') }}{% endblock %} + +{% block branding %} +

{{ site_header|default:_('Django administration') }}

+{% endblock %} + +{% block nav-global %}{% endblock %} diff --git a/rest_admin/templates/rest_admin/index.html b/rest_admin/templates/rest_admin/index.html new file mode 100644 index 0000000..0eb1d50 --- /dev/null +++ b/rest_admin/templates/rest_admin/index.html @@ -0,0 +1,87 @@ +{% extends "rest_admin/base_site.html" %} +{% load i18n admin_static %} + +{% block extrastyle %}{{ block.super }}{% endblock %} + +{% block bodyclass %}{{ block.super }} dashboard{% endblock %} + +{% block breadcrumbs %}{% endblock %} + +{% block content %} + +

Loading...

+ +{% comment %} +
+ +{% if app_list %} + {% for app in app_list %} +
+ + + {% for model in app.models %} + + {% if model.admin_url %} + + {% else %} + + {% endif %} + + {% if model.add_url %} + + {% else %} + + {% endif %} + + {% if model.admin_url %} + + {% else %} + + {% endif %} + + {% endfor %} +
+ {{ app.name }} +
{{ model.name }}{{ model.name }}{% trans 'Add' %} {% trans 'Change' %} 
+
+ {% endfor %} +{% else %} +

{% trans "You don't have permission to edit anything." %}

+{% endif %} +
+{% endcomment %} +{% endblock %} + +{% comment %} +{% block sidebar %} + +{% endblock %} +{% endcomment %} diff --git a/rest_admin/views.py b/rest_admin/views.py index 283d159..a51fafa 100644 --- a/rest_admin/views.py +++ b/rest_admin/views.py @@ -1,3 +1,4 @@ +from django.views.generic import TemplateView from rest_framework import generics from rest_framework.permissions import IsAdminUser @@ -12,3 +13,8 @@ class AdminAppsView(generics.ListAPIView): def get_queryset(self): return site.get_apps(self.request) + + +class AdminIndexView(TemplateView): + """Index view rendering base React HTML template by default""" + template_name = 'rest_admin/index.html' From b547398fefd5ecc66845b45a553161c9d4d3aec6 Mon Sep 17 00:00:00 2001 From: David Avs Date: Wed, 25 Nov 2015 09:39:00 -0500 Subject: [PATCH 2/3] view -> schema, and implement it using ViewSets --- rest_admin/sites.py | 56 ++++++++++++------- .../templates/rest_admin/base_site.html | 2 +- rest_admin/views.py | 4 +- 3 files changed, 38 insertions(+), 24 deletions(-) diff --git a/rest_admin/sites.py b/rest_admin/sites.py index 12af565..488802e 100644 --- a/rest_admin/sites.py +++ b/rest_admin/sites.py @@ -88,8 +88,14 @@ def get_apps(self, request): return sorted(filter(lambda itm: itm.models, app_dict.values()), key=lambda itm: itm.name) def get_api_urls(self): - from django.conf.urls import url - from .views import AdminAppsView + from .views import AppsViewSet + from rest_framework import routers + + router = routers.DefaultRouter() + router.register('apps', AppsViewSet, 'apps') + + return router.urls + # # Since this module gets imported in the application's root package, # # it cannot import models from other applications at the module level, # # and django.contrib.contenttypes.views imports ContentType. @@ -103,19 +109,18 @@ def get_api_urls(self): # return self.admin_view(view, cacheable)(*args, **kwargs) # return update_wrapper(wrapper, view) - # Admin-site-wide views. - urlpatterns = [ - # url(r'^$', wrap(self.index), name='index'), - url(r'^apps', AdminAppsView.as_view(), name='apps'), - # url(r'^login/$', self.login, name='login'), - # url(r'^logout/$', wrap(self.logout), name='logout'), - # url(r'^password_change/$', wrap(self.password_change, cacheable=True), name='password_change'), - # url(r'^password_change/done/$', wrap(self.password_change_done, cacheable=True), - # name='password_change_done'), - # url(r'^jsi18n/$', wrap(self.i18n_javascript, cacheable=True), name='jsi18n'), - # url(r'^r/(?P\d+)/(?P.+)/$', wrap(contenttype_views.shortcut), - # name='view_on_site'), - ] + # # Admin-site-wide views. + # urlpatterns = [ + # # url(r'^$', wrap(self.index), name='index'), + # # url(r'^login/$', self.login, name='login'), + # # url(r'^logout/$', wrap(self.logout), name='logout'), + # # url(r'^password_change/$', wrap(self.password_change, cacheable=True), name='password_change'), + # # url(r'^password_change/done/$', wrap(self.password_change_done, cacheable=True), + # # name='password_change_done'), + # # url(r'^jsi18n/$', wrap(self.i18n_javascript, cacheable=True), name='jsi18n'), + # # url(r'^r/(?P\d+)/(?P.+)/$', wrap(contenttype_views.shortcut), + # # name='view_on_site'), + # ] # # Add in each model's views, and create a list of valid URLS for the # # app_index @@ -135,13 +140,16 @@ def get_api_urls(self): # url(regex, wrap(self.app_index), name='app_list'), # ] - return urlpatterns + # return urlpatterns + + def get_schema_urls(self): + return [] # TODO - def get_view_urls(self): + def get_index_urls(self): from django.conf.urls import url from .views import AdminIndexView return [ - url('^', AdminIndexView.as_view(), name='index'), + url('^$', AdminIndexView.as_view(), name='index'), ] @property @@ -151,9 +159,14 @@ def api_urls(self): return (urlpatterns, 'rest_admin', self.name) @property - def view_urls(self): + def schema_urls(self): from django.conf.urls import url, include - urlpatterns = [url('^', include(self.get_view_urls(), namespace='view'))] + urlpatterns = [url('^', include(self.get_schema_urls(), namespace='schema'))] + return (urlpatterns, 'rest_admin', self.name) + + @property + def index_urls(self): + urlpatterns = self.get_index_urls() return (urlpatterns, 'rest_admin', self.name) @property @@ -161,7 +174,8 @@ def urls(self): from django.conf.urls import url, include urlpatterns = [ url('^api/', include(self.get_api_urls(), namespace='api')), - url('^', include(self.get_view_urls(), namespace='view')), + url('^schema/', include(self.get_schema_urls(), namespace='schema')), + url('^', include(self.get_index_urls())), ] return (urlpatterns, 'rest_admin', self.name) diff --git a/rest_admin/templates/rest_admin/base_site.html b/rest_admin/templates/rest_admin/base_site.html index 46a271a..37b8ec8 100644 --- a/rest_admin/templates/rest_admin/base_site.html +++ b/rest_admin/templates/rest_admin/base_site.html @@ -3,7 +3,7 @@ {% block title %}{{ title }} | {{ site_title|default:_('Django site admin') }}{% endblock %} {% block branding %} -

{{ site_header|default:_('Django administration') }}

+

{{ site_header|default:_('Django administration') }}

{% endblock %} {% block nav-global %}{% endblock %} diff --git a/rest_admin/views.py b/rest_admin/views.py index a51fafa..2aa3a8c 100644 --- a/rest_admin/views.py +++ b/rest_admin/views.py @@ -1,12 +1,12 @@ from django.views.generic import TemplateView -from rest_framework import generics +from rest_framework import viewsets, mixins from rest_framework.permissions import IsAdminUser from . import site from .serializers import AdminAppSerializer -class AdminAppsView(generics.ListAPIView): +class AppsViewSet(mixins.ListModelMixin, viewsets.GenericViewSet): """List of Admin apps with nested ModelAdmin instances""" serializer_class = AdminAppSerializer permission_classes = (IsAdminUser, ) From d48126bfbffc0cdc8e015f01424b54b964e488a6 Mon Sep 17 00:00:00 2001 From: David Avs Date: Wed, 6 Jan 2016 01:11:02 -0500 Subject: [PATCH 3/3] Compiling React using django-static-precompiler and Browserify --- .gitignore | 4 + requirements.txt | 2 + rest_admin/sites.py | 9 +- .../es6-module-loader-dev.js | 8 + .../es6-module-loader-dev.js.map | 1 + .../es6-module-loader-dev.src.js | 1639 +++++++++++++++++ .../js/es6-module-loader/es6-module-loader.js | 8 + .../es6-module-loader.js.map | 1 + .../es6-module-loader.src.js | 1260 +++++++++++++ rest_admin/static/js/rest_admin.js | 0 rest_admin/templates/rest_admin/base.html | 21 - rest_admin/templates/rest_admin/index.html | 5 + .../templates/rest_admin/schema/index.jsx | 25 + test_project/test_project/settings.py | 16 + 14 files changed, 2977 insertions(+), 22 deletions(-) create mode 100644 rest_admin/static/js/es6-module-loader/es6-module-loader-dev.js create mode 100644 rest_admin/static/js/es6-module-loader/es6-module-loader-dev.js.map create mode 100644 rest_admin/static/js/es6-module-loader/es6-module-loader-dev.src.js create mode 100644 rest_admin/static/js/es6-module-loader/es6-module-loader.js create mode 100644 rest_admin/static/js/es6-module-loader/es6-module-loader.js.map create mode 100644 rest_admin/static/js/es6-module-loader/es6-module-loader.src.js delete mode 100644 rest_admin/static/js/rest_admin.js delete mode 100644 rest_admin/templates/rest_admin/base.html create mode 100644 rest_admin/templates/rest_admin/schema/index.jsx diff --git a/.gitignore b/.gitignore index 5363db9..1865987 100644 --- a/.gitignore +++ b/.gitignore @@ -42,3 +42,7 @@ output/*/index.html # Sphinx docs/_build + + +# Node +/node_modules/ diff --git a/requirements.txt b/requirements.txt index 1b14121..a23695b 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1,2 +1,4 @@ django>=1.8.0 # Additional requirements go here + +-e git+git@github.com:avsd/django-static-precompiler.git@add_browserify#egg=django-static-precompiler diff --git a/rest_admin/sites.py b/rest_admin/sites.py index 488802e..a04ef04 100644 --- a/rest_admin/sites.py +++ b/rest_admin/sites.py @@ -143,7 +143,14 @@ def get_api_urls(self): # return urlpatterns def get_schema_urls(self): - return [] # TODO + from django.conf.urls import url + from django.views.generic import RedirectView, TemplateView + return [ + url('^$', RedirectView.as_view(url='/', permanent=False), name='schema-root'), + url('^index.jsx', + TemplateView.as_view(template_name='rest_admin/schema/index.jsx', content_type='text/jsx'), + name='index'), + ] # TODO def get_index_urls(self): from django.conf.urls import url diff --git a/rest_admin/static/js/es6-module-loader/es6-module-loader-dev.js b/rest_admin/static/js/es6-module-loader/es6-module-loader-dev.js new file mode 100644 index 0000000..6f38676 --- /dev/null +++ b/rest_admin/static/js/es6-module-loader/es6-module-loader-dev.js @@ -0,0 +1,8 @@ +/* + * es6-module-loader v0.17.9 + * https://github.com/ModuleLoader/es6-module-loader + * Copyright (c) 2015 Guy Bedford, Luke Hoban, Addy Osmani; Licensed MIT + */ + +!function(a){function b(a,c){if("string"!=typeof a)throw new TypeError("URL must be a string");var d=String(a).replace(/^\s+|\s+$/g,"").match(/^([^:\/?#]+:)?(?:\/\/(?:([^:@\/?#]*)(?::([^:@\/?#]*))?@)?(([^:\/?#]*)(?::(\d*))?))?([^?#]*)(\?[^#]*)?(#[\s\S]*)?/);if(!d)throw new RangeError;var e=d[1]||"",f=d[2]||"",g=d[3]||"",h=d[4]||"",i=d[5]||"",j=d[6]||"",k=d[7]||"",l=d[8]||"",m=d[9]||"";if(void 0!==c){var n=c instanceof b?c:new b(c),o=""===e&&""===h&&""===f;o&&""===k&&""===l&&(l=n.search),o&&"/"!==k.charAt(0)&&(k=""!==k?(""===n.host&&""===n.username||""!==n.pathname?"":"/")+n.pathname.slice(0,n.pathname.lastIndexOf("/")+1)+k:n.pathname);var p=[];k.replace(/^(\.\.?(\/|$))+/,"").replace(/\/(\.(\/|$))+/g,"/").replace(/\/\.\.$/,"/../").replace(/\/?[^\/]*/g,function(a){"/.."===a?p.pop():p.push(a)}),k=p.join("").replace(/^\//,"/"===k.charAt(0)?"/":""),o&&(j=n.port,i=n.hostname,h=n.host,g=n.password,f=n.username),""===e&&(e=n.protocol)}"file:"==e&&(k=k.replace(/\\/g,"/")),this.origin=e+(""!==e||""!==h?"//":"")+h,this.href=e+(""!==e||""!==h?"//":"")+(""!==f?f+(""!==g?":"+g:"")+"@":"")+h+k+l+m,this.protocol=e,this.username=f,this.password=g,this.host=h,this.hostname=i,this.port=j,this.pathname=k,this.search=l,this.hash=m}a.URLPolyfill=b}("undefined"!=typeof self?self:global),function(a){function b(a,b){var c;if(a instanceof Error){var c=new Error(a.message,a.fileName,a.lineNumber);i?(c.message=a.message+"\n "+b,c.stack=a.stack):(c.message=a.message,c.stack=a.stack+"\n "+b)}else c=a+"\n "+b;return c}function c(a,c,d){try{new Function(a).call(d)}catch(e){throw b(e,"Evaluating "+c)}}function d(){}function e(b){this._loader={loaderObj:this,loads:[],modules:{},importPromises:{},moduleRecords:{}},k(this,"global",{get:function(){return a}})}function f(){e.call(this),this.paths={}}function g(a,b){var c,d="",e=0;for(var f in a){var g=f.split("*");if(g.length>2)throw new TypeError("Only one wildcard in a path is permitted");if(1==g.length){if(b==f){d=f;break}}else{var h=g[0].length;h>=e&&b.substr(0,g[0].length)==g[0]&&b.substr(b.length-g[1].length)==g[1]&&(e=h,d=f,c=b.substr(g[0].length,b.length-g[1].length-g[0].length))}}var i=a[d]||b;return"string"==typeof c&&(i=i.replace("*",c)),i}function h(){}var i=("undefined"==typeof window&&"undefined"!=typeof self&&"undefined"!=typeof importScripts,"undefined"!=typeof window&&"undefined"!=typeof document),j="undefined"!=typeof process&&!!process.platform.match(/^win/);a.console||(a.console={assert:function(){}});var k,l=Array.prototype.indexOf||function(a){for(var b=0,c=this.length;c>b;b++)if(this[b]===a)return b;return-1};!function(){try{Object.defineProperty({},"a",{})&&(k=Object.defineProperty)}catch(a){k=function(a,b,c){try{a[b]=c.value||c.get.call(a)}catch(d){}}}}();var m;if("undefined"!=typeof document&&document.getElementsByTagName){if(m=document.baseURI,!m){var n=document.getElementsByTagName("base");m=n[0]&&n[0].href||window.location.href}m=m.split("#")[0].split("?")[0],m=m.substr(0,m.lastIndexOf("/")+1)}else if("undefined"!=typeof process&&process.cwd)m="file://"+(j?"/":"")+process.cwd()+"/",j&&(m=m.replace(/\\/g,"/"));else{if("undefined"==typeof location)throw new TypeError("No environment baseURI");m=a.location.href}var o=a.URLPolyfill||a.URL;k(d.prototype,"toString",{value:function(){return"Module"}}),function(){function f(a){return{status:"loading",name:a,linkSets:[],dependencies:[],metadata:{}}}function g(a,b,c){return new Promise(n({step:c.address?"fetch":"locate",loader:a,moduleName:b,moduleMetadata:c&&c.metadata||{},moduleSource:c.source,moduleAddress:c.address}))}function h(a,b,c,d){return new Promise(function(e,f){e(a.loaderObj.normalize(b,c,d))}).then(function(b){var c;if(a.modules[b])return c=f(b),c.status="linked",c.module=a.modules[b],c;for(var d=0,e=a.loads.length;e>d;d++)if(c=a.loads[d],c.name==b)return c;return c=f(b),a.loads.push(c),i(a,c),c})}function i(a,b){j(a,b,Promise.resolve().then(function(){return a.loaderObj.locate({name:b.name,metadata:b.metadata})}))}function j(a,b,c){m(a,b,c.then(function(c){return"loading"==b.status?(b.address=c,a.loaderObj.fetch({name:b.name,metadata:b.metadata,address:c})):void 0}))}function m(b,d,e){e.then(function(e){return"loading"==d.status?Promise.resolve(b.loaderObj.translate({name:d.name,metadata:d.metadata,address:d.address,source:e})).then(function(a){return d.source=a,b.loaderObj.instantiate({name:d.name,metadata:d.metadata,address:d.address,source:a})}).then(function(e){if(void 0===e)return d.address=d.address||"",d.isDeclarative=!0,q.call(b.loaderObj,d).then(function(b){var e=a.System,f=e.register;e.register=function(a,b,c){"string"!=typeof a&&(c=b,b=a),d.declare=c,d.depsList=b},c(b,d.address,{}),e.register=f});if("object"!=typeof e)throw TypeError("Invalid instantiate return value");d.depsList=e.deps||[],d.execute=e.execute,d.isDeclarative=!1}).then(function(){d.dependencies=[];for(var a=d.depsList,c=[],e=0,f=a.length;f>e;e++)(function(a,e){c.push(h(b,a,d.name,d.address).then(function(b){if(d.dependencies[e]={key:a,value:b.name},"linked"!=b.status)for(var c=d.linkSets.concat([]),f=0,g=c.length;g>f;f++)p(c[f],b)}))})(a[e],e);return Promise.all(c)}).then(function(){d.status="loaded";for(var a=d.linkSets.concat([]),b=0,c=a.length;c>b;b++)s(a[b],d)}):void 0})["catch"](function(a){d.status="failed",d.exception=a;for(var b=d.linkSets.concat([]),c=0,e=b.length;e>c;c++)t(b[c],d,a)})}function n(a){return function(b,c){var d=a.loader,e=a.moduleName,g=a.step;if(d.modules[e])throw new TypeError('"'+e+'" already exists in the module table');for(var h,k=0,l=d.loads.length;l>k;k++)if(d.loads[k].name==e&&(h=d.loads[k],"translate"!=g||h.source||(h.address=a.moduleAddress,m(d,h,Promise.resolve(a.moduleSource))),h.linkSets.length&&h.linkSets[0].loads[0].name==h.name))return h.linkSets[0].done.then(function(){b(h)});var n=h||f(e);n.metadata=a.moduleMetadata;var p=o(d,n);d.loads.push(n),b(p.done),"locate"==g?i(d,n):"fetch"==g?j(d,n,Promise.resolve(a.moduleAddress)):(n.address=a.moduleAddress,m(d,n,Promise.resolve(a.moduleSource)))}}function o(a,b){var c={loader:a,loads:[],startingLoad:b,loadingCount:0};return c.done=new Promise(function(a,b){c.resolve=a,c.reject=b}),p(c,b),c}function p(a,b){if("failed"!=b.status){for(var c=0,d=a.loads.length;d>c;c++)if(a.loads[c]==b)return;a.loads.push(b),b.linkSets.push(a),"loaded"!=b.status&&a.loadingCount++;for(var e=a.loader,c=0,d=b.dependencies.length;d>c;c++)if(b.dependencies[c]){var f=b.dependencies[c].value;if(!e.modules[f])for(var g=0,h=e.loads.length;h>g;g++)if(e.loads[g].name==f){p(a,e.loads[g]);break}}}}function r(a){var b=!1;try{y(a,function(c,d){t(a,c,d),b=!0})}catch(c){t(a,null,c),b=!0}return b}function s(a,b){if(a.loadingCount--,!(a.loadingCount>0)){var c=a.startingLoad;if(a.loader.loaderObj.execute===!1){for(var d=[].concat(a.loads),e=0,f=d.length;f>e;e++){var b=d[e];b.module=b.isDeclarative?{name:b.name,module:G({}),evaluated:!0}:{module:G({})},b.status="linked",u(a.loader,b)}return a.resolve(c)}var g=r(a);g||a.resolve(c)}}function t(a,c,d){var e=a.loader;a:if(c)if(a.loads[0].name==c.name)d=b(d,"Error loading "+c.name);else{for(var f=0;ff;f++){var c=j[f];e.loaderObj.failed=e.loaderObj.failed||[],-1==l.call(e.loaderObj.failed,c)&&e.loaderObj.failed.push(c);var m=l.call(c.linkSets,a);if(c.linkSets.splice(m,1),0==c.linkSets.length){var n=l.call(a.loader.loads,c);-1!=n&&a.loader.loads.splice(n,1)}}a.reject(d)}function u(a,b){if(a.loaderObj.trace){a.loaderObj.loads||(a.loaderObj.loads={});var c={};b.dependencies.forEach(function(a){c[a.key]=a.value}),a.loaderObj.loads[b.name]={name:b.name,deps:b.dependencies.map(function(a){return a.key}),depMap:c,address:b.address,metadata:b.metadata,source:b.source,kind:b.isDeclarative?"declarative":"dynamic"}}b.name&&(a.modules[b.name]=b.module);var d=l.call(a.loads,b);-1!=d&&a.loads.splice(d,1);for(var e=0,f=b.linkSets.length;f>e;e++)d=l.call(b.linkSets[e].loads,b),-1!=d&&b.linkSets[e].loads.splice(d,1);b.linkSets.splice(0,b.linkSets.length)}function v(a,b,c){try{var e=b.execute()}catch(f){return void c(b,f)}return e&&e instanceof d?e:void c(b,new TypeError("Execution must define a Module instance"))}function w(a,b,c){var d=a._loader.importPromises;return d[b]=c.then(function(a){return d[b]=void 0,a},function(a){throw d[b]=void 0,a})}function x(a,b,c){if(c[a.groupIndex]=c[a.groupIndex]||[],-1==l.call(c[a.groupIndex],a)){c[a.groupIndex].push(a);for(var d=0,e=b.length;e>d;d++)for(var f=b[d],g=0;g=0;g--){for(var h=d[g],i=0;id;d++){var h=e.importers[d];if(!h.locked)for(var i=0;ih;h++){var j=b.dependencies[h].value,k=d.modules[j];if(!k)for(var l=0;lg;g++){var i=f[g];if(i&&-1==l.call(c,i)&&(e=E(i,c,d)))return e=b(e,"Error evaluating "+i.name)}if(a.failed)return new Error("Module failed execution.");if(!a.evaluated)return a.evaluated=!0,e=B(a),e?a.failed=!0:Object.preventExtensions&&Object.preventExtensions(a.module),a.execute=void 0,e}}var F=0;e.prototype={constructor:e,define:function(a,b,c){if(this._loader.importPromises[a])throw new TypeError("Module is already loading.");return w(this,a,new Promise(n({step:"translate",loader:this._loader,moduleName:a,moduleMetadata:c&&c.metadata||{},moduleSource:b,moduleAddress:c&&c.address})))},"delete":function(a){var b=this._loader;return delete b.importPromises[a],delete b.moduleRecords[a],b.modules[a]?delete b.modules[a]:!1},get:function(a){return this._loader.modules[a]?(D(this._loader.modules[a],[],this),this._loader.modules[a].module):void 0},has:function(a){return!!this._loader.modules[a]},"import":function(a,b,c){"object"==typeof b&&(b=b.name);var d=this;return Promise.resolve(d.normalize(a,b)).then(function(a){var b=d._loader;return b.modules[a]?(D(b.modules[a],[],b._loader),b.modules[a].module):b.importPromises[a]||w(d,a,g(b,a,{}).then(function(c){return delete b.importPromises[a],C(b,c)}))})},load:function(a,b){var c=this._loader;return c.modules[a]?(D(c.modules[a],[],c),Promise.resolve(c.modules[a].module)):c.importPromises[a]||w(this,a,g(c,a,{}).then(function(b){return delete c.importPromises[a],C(c,b)}))},module:function(a,b){var c=f();c.address=b&&b.address;var d=o(this._loader,c),e=Promise.resolve(a),g=this._loader,h=d.done.then(function(){return C(g,c)});return m(g,c,e),h},newModule:function(a){if("object"!=typeof a)throw new TypeError("Expected object");var b=new d,c=[];if(Object.getOwnPropertyNames&&null!=a)c=Object.getOwnPropertyNames(a);else for(var e in a)c.push(e);for(var f=0;f load contains linkSet'); + + if (load.linkSets.indexOf(linkSet) != -1) + console.assert(linkSet.loads.indexOf(load) != -1, 'load contains linkSet -> linkSet contains load'); + } + } + + for (var i = 0; i < linkSets.length; i++) { + var linkSet = linkSets[i]; + for (var j = 0; j < linkSet.loads.length; j++) { + var load = linkSet.loads[j]; + + for (var k = 0; k < load.dependencies.length; k++) { + var depName = load.dependencies[k].value; + var depLoad; + for (var l = 0; l < loads.length; l++) { + if (loads[l].name != depName) + continue; + depLoad = loads[l]; + break; + } + + // loading records are allowed not to have their dependencies yet + // if (load.status != 'loading') + // console.assert(depLoad, 'depLoad found'); + + // console.assert(linkSet.loads.indexOf(depLoad) != -1, 'linkset contains all dependencies'); + } + } + } +} */ + + // 15.2.3 - Runtime Semantics: Loader State + + // 15.2.3.11 + function createLoaderLoad(object) { + return { + // modules is an object for ES5 implementation + modules: {}, + loads: [], + loaderObj: object + }; + } + + // 15.2.3.2 Load Records and LoadRequest Objects + + // 15.2.3.2.1 + function createLoad(name) { + return { + status: 'loading', + name: name, + linkSets: [], + dependencies: [], + metadata: {} + }; + } + + // 15.2.3.2.2 createLoadRequestObject, absorbed into calling functions + + // 15.2.4 + + // 15.2.4.1 + function loadModule(loader, name, options) { + return new Promise(asyncStartLoadPartwayThrough({ + step: options.address ? 'fetch' : 'locate', + loader: loader, + moduleName: name, + // allow metadata for import https://bugs.ecmascript.org/show_bug.cgi?id=3091 + moduleMetadata: options && options.metadata || {}, + moduleSource: options.source, + moduleAddress: options.address + })); + } + + // 15.2.4.2 + function requestLoad(loader, request, refererName, refererAddress) { + // 15.2.4.2.1 CallNormalize + return new Promise(function(resolve, reject) { + resolve(loader.loaderObj.normalize(request, refererName, refererAddress)); + }) + // 15.2.4.2.2 GetOrCreateLoad + .then(function(name) { + var load; + if (loader.modules[name]) { + load = createLoad(name); + load.status = 'linked'; + // https://bugs.ecmascript.org/show_bug.cgi?id=2795 + load.module = loader.modules[name]; + return load; + } + + for (var i = 0, l = loader.loads.length; i < l; i++) { + load = loader.loads[i]; + if (load.name != name) + continue; + console.assert(load.status == 'loading' || load.status == 'loaded', 'loading or loaded'); + return load; + } + + load = createLoad(name); + loader.loads.push(load); + + proceedToLocate(loader, load); + + return load; + }); + } + + // 15.2.4.3 + function proceedToLocate(loader, load) { + proceedToFetch(loader, load, + Promise.resolve() + // 15.2.4.3.1 CallLocate + .then(function() { + return loader.loaderObj.locate({ name: load.name, metadata: load.metadata }); + }) + ); + } + + // 15.2.4.4 + function proceedToFetch(loader, load, p) { + proceedToTranslate(loader, load, + p + // 15.2.4.4.1 CallFetch + .then(function(address) { + // adjusted, see https://bugs.ecmascript.org/show_bug.cgi?id=2602 + if (load.status != 'loading') + return; + load.address = address; + + return loader.loaderObj.fetch({ name: load.name, metadata: load.metadata, address: address }); + }) + ); + } + + var anonCnt = 0; + + // 15.2.4.5 + function proceedToTranslate(loader, load, p) { + p + // 15.2.4.5.1 CallTranslate + .then(function(source) { + if (load.status != 'loading') + return; + + return Promise.resolve(loader.loaderObj.translate({ name: load.name, metadata: load.metadata, address: load.address, source: source })) + + // 15.2.4.5.2 CallInstantiate + .then(function(source) { + load.source = source; + return loader.loaderObj.instantiate({ name: load.name, metadata: load.metadata, address: load.address, source: source }); + }) + + // 15.2.4.5.3 InstantiateSucceeded + .then(function(instantiateResult) { + if (instantiateResult === undefined) { + load.address = load.address || ''; + + // instead of load.kind, use load.isDeclarative + load.isDeclarative = true; + return transpile.call(loader.loaderObj, load) + .then(function(transpiled) { + // Hijack System.register to set declare function + var curSystem = __global.System; + var curRegister = curSystem.register; + curSystem.register = function(name, deps, declare) { + if (typeof name != 'string') { + declare = deps; + deps = name; + } + // store the registered declaration as load.declare + // store the deps as load.deps + load.declare = declare; + load.depsList = deps; + } + // empty {} context is closest to undefined 'this' we can get + __eval(transpiled, load.address, {}); + curSystem.register = curRegister; + }); + } + else if (typeof instantiateResult == 'object') { + load.depsList = instantiateResult.deps || []; + load.execute = instantiateResult.execute; + load.isDeclarative = false; + } + else + throw TypeError('Invalid instantiate return value'); + }) + // 15.2.4.6 ProcessLoadDependencies + .then(function() { + load.dependencies = []; + var depsList = load.depsList; + + var loadPromises = []; + for (var i = 0, l = depsList.length; i < l; i++) (function(request, index) { + loadPromises.push( + requestLoad(loader, request, load.name, load.address) + + // 15.2.4.6.1 AddDependencyLoad (load is parentLoad) + .then(function(depLoad) { + + // adjusted from spec to maintain dependency order + // this is due to the System.register internal implementation needs + load.dependencies[index] = { + key: request, + value: depLoad.name + }; + + if (depLoad.status != 'linked') { + var linkSets = load.linkSets.concat([]); + for (var i = 0, l = linkSets.length; i < l; i++) + addLoadToLinkSet(linkSets[i], depLoad); + } + + // console.log('AddDependencyLoad ' + depLoad.name + ' for ' + load.name); + // snapshot(loader); + }) + ); + })(depsList[i], i); + + return Promise.all(loadPromises); + }) + + // 15.2.4.6.2 LoadSucceeded + .then(function() { + // console.log('LoadSucceeded ' + load.name); + // snapshot(loader); + + console.assert(load.status == 'loading', 'is loading'); + + load.status = 'loaded'; + + var linkSets = load.linkSets.concat([]); + for (var i = 0, l = linkSets.length; i < l; i++) + updateLinkSetOnLoad(linkSets[i], load); + }); + }) + // 15.2.4.5.4 LoadFailed + ['catch'](function(exc) { + load.status = 'failed'; + load.exception = exc; + + var linkSets = load.linkSets.concat([]); + for (var i = 0, l = linkSets.length; i < l; i++) { + linkSetFailed(linkSets[i], load, exc); + } + + console.assert(load.linkSets.length == 0, 'linkSets not removed'); + }); + } + + // 15.2.4.7 PromiseOfStartLoadPartwayThrough absorbed into calling functions + + // 15.2.4.7.1 + function asyncStartLoadPartwayThrough(stepState) { + return function(resolve, reject) { + var loader = stepState.loader; + var name = stepState.moduleName; + var step = stepState.step; + + if (loader.modules[name]) + throw new TypeError('"' + name + '" already exists in the module table'); + + // adjusted to pick up existing loads + var existingLoad; + for (var i = 0, l = loader.loads.length; i < l; i++) { + if (loader.loads[i].name == name) { + existingLoad = loader.loads[i]; + + if (step == 'translate' && !existingLoad.source) { + existingLoad.address = stepState.moduleAddress; + proceedToTranslate(loader, existingLoad, Promise.resolve(stepState.moduleSource)); + } + + // a primary load -> use that existing linkset if it is for the direct load here + // otherwise create a new linkset unit + if (existingLoad.linkSets.length && existingLoad.linkSets[0].loads[0].name == existingLoad.name) + return existingLoad.linkSets[0].done.then(function() { + resolve(existingLoad); + }); + } + } + + var load = existingLoad || createLoad(name); + + load.metadata = stepState.moduleMetadata; + + var linkSet = createLinkSet(loader, load); + + loader.loads.push(load); + + resolve(linkSet.done); + + if (step == 'locate') + proceedToLocate(loader, load); + + else if (step == 'fetch') + proceedToFetch(loader, load, Promise.resolve(stepState.moduleAddress)); + + else { + console.assert(step == 'translate', 'translate step'); + load.address = stepState.moduleAddress; + proceedToTranslate(loader, load, Promise.resolve(stepState.moduleSource)); + } + } + } + + // Declarative linking functions run through alternative implementation: + // 15.2.5.1.1 CreateModuleLinkageRecord not implemented + // 15.2.5.1.2 LookupExport not implemented + // 15.2.5.1.3 LookupModuleDependency not implemented + + // 15.2.5.2.1 + function createLinkSet(loader, startingLoad) { + var linkSet = { + loader: loader, + loads: [], + startingLoad: startingLoad, // added see spec bug https://bugs.ecmascript.org/show_bug.cgi?id=2995 + loadingCount: 0 + }; + linkSet.done = new Promise(function(resolve, reject) { + linkSet.resolve = resolve; + linkSet.reject = reject; + }); + addLoadToLinkSet(linkSet, startingLoad); + return linkSet; + } + // 15.2.5.2.2 + function addLoadToLinkSet(linkSet, load) { + if (load.status == 'failed') + return; + + console.assert(load.status == 'loading' || load.status == 'loaded', 'loading or loaded on link set'); + + for (var i = 0, l = linkSet.loads.length; i < l; i++) + if (linkSet.loads[i] == load) + return; + + linkSet.loads.push(load); + load.linkSets.push(linkSet); + + // adjustment, see https://bugs.ecmascript.org/show_bug.cgi?id=2603 + if (load.status != 'loaded') { + linkSet.loadingCount++; + } + + var loader = linkSet.loader; + + for (var i = 0, l = load.dependencies.length; i < l; i++) { + if (!load.dependencies[i]) + continue; + + var name = load.dependencies[i].value; + + if (loader.modules[name]) + continue; + + for (var j = 0, d = loader.loads.length; j < d; j++) { + if (loader.loads[j].name != name) + continue; + + addLoadToLinkSet(linkSet, loader.loads[j]); + break; + } + } + // console.log('add to linkset ' + load.name); + // snapshot(linkSet.loader); + } + + // linking errors can be generic or load-specific + // this is necessary for debugging info + function doLink(linkSet) { + var error = false; + try { + link(linkSet, function(load, exc) { + linkSetFailed(linkSet, load, exc); + error = true; + }); + } + catch(e) { + linkSetFailed(linkSet, null, e); + error = true; + } + return error; + } + + // 15.2.5.2.3 + function updateLinkSetOnLoad(linkSet, load) { + // console.log('update linkset on load ' + load.name); + // snapshot(linkSet.loader); + + console.assert(load.status == 'loaded' || load.status == 'linked', 'loaded or linked'); + + linkSet.loadingCount--; + + if (linkSet.loadingCount > 0) + return; + + // adjusted for spec bug https://bugs.ecmascript.org/show_bug.cgi?id=2995 + var startingLoad = linkSet.startingLoad; + + // non-executing link variation for loader tracing + // on the server. Not in spec. + /***/ + if (linkSet.loader.loaderObj.execute === false) { + var loads = [].concat(linkSet.loads); + for (var i = 0, l = loads.length; i < l; i++) { + var load = loads[i]; + load.module = !load.isDeclarative ? { + module: _newModule({}) + } : { + name: load.name, + module: _newModule({}), + evaluated: true + }; + load.status = 'linked'; + finishLoad(linkSet.loader, load); + } + return linkSet.resolve(startingLoad); + } + /***/ + + var abrupt = doLink(linkSet); + + if (abrupt) + return; + + console.assert(linkSet.loads.length == 0, 'loads cleared'); + + linkSet.resolve(startingLoad); + } + + // 15.2.5.2.4 + function linkSetFailed(linkSet, load, exc) { + var loader = linkSet.loader; + var requests; + + checkError: + if (load) { + if (linkSet.loads[0].name == load.name) { + exc = addToError(exc, 'Error loading ' + load.name); + } + else { + for (var i = 0; i < linkSet.loads.length; i++) { + var pLoad = linkSet.loads[i]; + for (var j = 0; j < pLoad.dependencies.length; j++) { + var dep = pLoad.dependencies[j]; + if (dep.value == load.name) { + exc = addToError(exc, 'Error loading ' + load.name + ' as "' + dep.key + '" from ' + pLoad.name); + break checkError; + } + } + } + exc = addToError(exc, 'Error loading ' + load.name + ' from ' + linkSet.loads[0].name); + } + } + else { + exc = addToError(exc, 'Error linking ' + linkSet.loads[0].name); + } + + + var loads = linkSet.loads.concat([]); + for (var i = 0, l = loads.length; i < l; i++) { + var load = loads[i]; + + // store all failed load records + loader.loaderObj.failed = loader.loaderObj.failed || []; + if (indexOf.call(loader.loaderObj.failed, load) == -1) + loader.loaderObj.failed.push(load); + + var linkIndex = indexOf.call(load.linkSets, linkSet); + console.assert(linkIndex != -1, 'link not present'); + load.linkSets.splice(linkIndex, 1); + if (load.linkSets.length == 0) { + var globalLoadsIndex = indexOf.call(linkSet.loader.loads, load); + if (globalLoadsIndex != -1) + linkSet.loader.loads.splice(globalLoadsIndex, 1); + } + } + linkSet.reject(exc); + } + + // 15.2.5.2.5 + function finishLoad(loader, load) { + // add to global trace if tracing + if (loader.loaderObj.trace) { + if (!loader.loaderObj.loads) + loader.loaderObj.loads = {}; + var depMap = {}; + load.dependencies.forEach(function(dep) { + depMap[dep.key] = dep.value; + }); + loader.loaderObj.loads[load.name] = { + name: load.name, + deps: load.dependencies.map(function(dep){ return dep.key }), + depMap: depMap, + address: load.address, + metadata: load.metadata, + source: load.source, + kind: load.isDeclarative ? 'declarative' : 'dynamic' + }; + } + // if not anonymous, add to the module table + if (load.name) { + console.assert(!loader.modules[load.name], 'load not in module table'); + loader.modules[load.name] = load.module; + } + var loadIndex = indexOf.call(loader.loads, load); + if (loadIndex != -1) + loader.loads.splice(loadIndex, 1); + for (var i = 0, l = load.linkSets.length; i < l; i++) { + loadIndex = indexOf.call(load.linkSets[i].loads, load); + if (loadIndex != -1) + load.linkSets[i].loads.splice(loadIndex, 1); + } + load.linkSets.splice(0, load.linkSets.length); + } + + function doDynamicExecute(linkSet, load, linkError) { + try { + var module = load.execute(); + } + catch(e) { + linkError(load, e); + return; + } + if (!module || !(module instanceof Module)) + linkError(load, new TypeError('Execution must define a Module instance')); + else + return module; + } + + // 26.3 Loader + + // 26.3.1.1 + // defined at top + + // importPromises adds ability to import a module twice without error - https://bugs.ecmascript.org/show_bug.cgi?id=2601 + function createImportPromise(loader, name, promise) { + var importPromises = loader._loader.importPromises; + return importPromises[name] = promise.then(function(m) { + importPromises[name] = undefined; + return m; + }, function(e) { + importPromises[name] = undefined; + throw e; + }); + } + + Loader.prototype = { + // 26.3.3.1 + constructor: Loader, + // 26.3.3.2 + define: function(name, source, options) { + // check if already defined + if (this._loader.importPromises[name]) + throw new TypeError('Module is already loading.'); + return createImportPromise(this, name, new Promise(asyncStartLoadPartwayThrough({ + step: 'translate', + loader: this._loader, + moduleName: name, + moduleMetadata: options && options.metadata || {}, + moduleSource: source, + moduleAddress: options && options.address + }))); + }, + // 26.3.3.3 + 'delete': function(name) { + var loader = this._loader; + delete loader.importPromises[name]; + delete loader.moduleRecords[name]; + return loader.modules[name] ? delete loader.modules[name] : false; + }, + // 26.3.3.4 entries not implemented + // 26.3.3.5 + get: function(key) { + if (!this._loader.modules[key]) + return; + doEnsureEvaluated(this._loader.modules[key], [], this); + return this._loader.modules[key].module; + }, + // 26.3.3.7 + has: function(name) { + return !!this._loader.modules[name]; + }, + // 26.3.3.8 + 'import': function(name, parentName, parentAddress) { + if (typeof parentName == 'object') + parentName = parentName.name; + + // run normalize first + var loaderObj = this; + + // added, see https://bugs.ecmascript.org/show_bug.cgi?id=2659 + return Promise.resolve(loaderObj.normalize(name, parentName)) + .then(function(name) { + var loader = loaderObj._loader; + + if (loader.modules[name]) { + doEnsureEvaluated(loader.modules[name], [], loader._loader); + return loader.modules[name].module; + } + + return loader.importPromises[name] || createImportPromise(loaderObj, name, + loadModule(loader, name, {}) + .then(function(load) { + delete loader.importPromises[name]; + return evaluateLoadedModule(loader, load); + })); + }); + }, + // 26.3.3.9 keys not implemented + // 26.3.3.10 + load: function(name, options) { + var loader = this._loader; + if (loader.modules[name]) { + doEnsureEvaluated(loader.modules[name], [], loader); + return Promise.resolve(loader.modules[name].module); + } + return loader.importPromises[name] || createImportPromise(this, name, + loadModule(loader, name, {}) + .then(function(load) { + delete loader.importPromises[name]; + return evaluateLoadedModule(loader, load); + })); + }, + // 26.3.3.11 + module: function(source, options) { + var load = createLoad(); + load.address = options && options.address; + var linkSet = createLinkSet(this._loader, load); + var sourcePromise = Promise.resolve(source); + var loader = this._loader; + var p = linkSet.done.then(function() { + return evaluateLoadedModule(loader, load); + }); + proceedToTranslate(loader, load, sourcePromise); + return p; + }, + // 26.3.3.12 + newModule: function (obj) { + if (typeof obj != 'object') + throw new TypeError('Expected object'); + + var m = new Module(); + + var pNames = []; + if (Object.getOwnPropertyNames && obj != null) + pNames = Object.getOwnPropertyNames(obj); + else + for (var key in obj) + pNames.push(key); + + for (var i = 0; i < pNames.length; i++) (function(key) { + defineProperty(m, key, { + configurable: false, + enumerable: true, + get: function () { + return obj[key]; + } + }); + })(pNames[i]); + + return m; + }, + // 26.3.3.14 + set: function(name, module) { + if (!(module instanceof Module)) + throw new TypeError('Loader.set(' + name + ', module) must be a module'); + this._loader.modules[name] = { + module: module + }; + }, + // 26.3.3.15 values not implemented + // 26.3.3.16 @@iterator not implemented + // 26.3.3.17 @@toStringTag not implemented + + // 26.3.3.18.1 + normalize: function(name, referrerName, referrerAddress) { + return name; + }, + // 26.3.3.18.2 + locate: function(load) { + return load.name; + }, + // 26.3.3.18.3 + fetch: function(load) { + }, + // 26.3.3.18.4 + translate: function(load) { + return load.source; + }, + // 26.3.3.18.5 + instantiate: function(load) { + } + }; + + var _newModule = Loader.prototype.newModule; + +/* + * ES6 Module Declarative Linking Code - Dev Build Only + */ + + // 15.2.5.3 Module Linking Groups + + // 15.2.5.3.2 BuildLinkageGroups alternative implementation + // Adjustments (also see https://bugs.ecmascript.org/show_bug.cgi?id=2755) + // 1. groups is an already-interleaved array of group kinds + // 2. load.groupIndex is set when this function runs + // 3. load.groupIndex is the interleaved index ie 0 declarative, 1 dynamic, 2 declarative, ... (or starting with dynamic) + function buildLinkageGroups(load, loads, groups) { + groups[load.groupIndex] = groups[load.groupIndex] || []; + + // if the load already has a group index and its in its group, its already been done + // this logic naturally handles cycles + if (indexOf.call(groups[load.groupIndex], load) != -1) + return; + + // now add it to the group to indicate its been seen + groups[load.groupIndex].push(load); + + for (var i = 0, l = loads.length; i < l; i++) { + var loadDep = loads[i]; + + // dependencies not found are already linked + for (var j = 0; j < load.dependencies.length; j++) { + if (loadDep.name == load.dependencies[j].value) { + // by definition all loads in linkset are loaded, not linked + console.assert(loadDep.status == 'loaded', 'Load in linkSet not loaded!'); + + // if it is a group transition, the index of the dependency has gone up + // otherwise it is the same as the parent + var loadDepGroupIndex = load.groupIndex + (loadDep.isDeclarative != load.isDeclarative); + + // the group index of an entry is always the maximum + if (loadDep.groupIndex === undefined || loadDep.groupIndex < loadDepGroupIndex) { + + // if already in a group, remove from the old group + if (loadDep.groupIndex !== undefined) { + groups[loadDep.groupIndex].splice(indexOf.call(groups[loadDep.groupIndex], loadDep), 1); + + // if the old group is empty, then we have a mixed depndency cycle + if (groups[loadDep.groupIndex].length == 0) + throw new TypeError("Mixed dependency cycle detected"); + } + + loadDep.groupIndex = loadDepGroupIndex; + } + + buildLinkageGroups(loadDep, loads, groups); + } + } + } + } + + // 15.2.5.4 + // declarative linking implementation + function link(linkSet, linkError) { + + var loader = linkSet.loader; + + if (!linkSet.loads.length) + return; + + // console.log('linking {' + logloads(linkSet.loads) + '}'); + // snapshot(loader); + + // 15.2.5.3.1 LinkageGroups alternative implementation + + // build all the groups + // because the first load represents the top of the tree + // for a given linkset, we can work down from there + var groups = []; + var startingLoad = linkSet.loads[0]; + startingLoad.groupIndex = 0; + buildLinkageGroups(startingLoad, linkSet.loads, groups); + + // determine the kind of the bottom group + var curGroupDeclarative = startingLoad.isDeclarative == groups.length % 2; + + // run through the groups from bottom to top + for (var i = groups.length - 1; i >= 0; i--) { + var group = groups[i]; + for (var j = 0; j < group.length; j++) { + var load = group[j]; + + // 15.2.5.5 LinkDeclarativeModules adjusted + if (curGroupDeclarative) { + linkDeclarativeModule(load, linkSet.loads, loader); + } + // 15.2.5.6 LinkDynamicModules adjusted + else { + var module = doDynamicExecute(linkSet, load, linkError); + if (!module) + return; + load.module = { + name: load.name, + module: module + }; + load.status = 'linked'; + } + finishLoad(loader, load); + } + + // alternative current kind for next loop + curGroupDeclarative = !curGroupDeclarative; + } + } + + + // custom module records for binding graph + // store linking module records in a separate table + function getOrCreateModuleRecord(name, loader) { + var moduleRecords = loader.moduleRecords; + return moduleRecords[name] || (moduleRecords[name] = { + name: name, + dependencies: [], + module: new Module(), // start from an empty module and extend + importers: [] + }); + } + + // custom declarative linking function + function linkDeclarativeModule(load, loads, loader) { + if (load.module) + return; + + var module = load.module = getOrCreateModuleRecord(load.name, loader); + var moduleObj = load.module.module; + + var registryEntry = load.declare.call(__global, function(name, value) { + // NB This should be an Object.defineProperty, but that is very slow. + // By disaling this module write-protection we gain performance. + // It could be useful to allow an option to enable or disable this. + module.locked = true; + + // export({name: value}) + if (typeof name == 'object') { + for (var p in name) + moduleObj[p] = name[p]; + } + // export(name, value) + else { + moduleObj[name] = value; + } + + for (var i = 0, l = module.importers.length; i < l; i++) { + var importerModule = module.importers[i]; + if (!importerModule.locked) { + for (var j = 0; j < importerModule.dependencies.length; ++j) { + if (importerModule.dependencies[j] === module) { + importerModule.setters[j](moduleObj); + } + } + } + } + + module.locked = false; + return value; + }, load.name); + + // setup our setters and execution function + module.setters = registryEntry.setters; + module.execute = registryEntry.execute; + + // now link all the module dependencies + // amending the depMap as we go + for (var i = 0, l = load.dependencies.length; i < l; i++) { + var depName = load.dependencies[i].value; + var depModule = loader.modules[depName]; + + // if dependency not already in the module registry + // then try and link it now + if (!depModule) { + // get the dependency load record + for (var j = 0; j < loads.length; j++) { + if (loads[j].name != depName) + continue; + + // only link if already not already started linking (stops at circular / dynamic) + if (!loads[j].module) { + linkDeclarativeModule(loads[j], loads, loader); + depModule = loads[j].module; + } + // if circular, create the module record + else { + depModule = getOrCreateModuleRecord(depName, loader); + } + } + } + + // only declarative modules have dynamic bindings + if (depModule.importers) { + module.dependencies.push(depModule); + depModule.importers.push(module); + } + else { + // track dynamic records as null module records as already linked + module.dependencies.push(null); + } + + // run the setter for this dependency + if (module.setters[i]) + module.setters[i](depModule.module); + } + + load.status = 'linked'; + } + + /* + * Module Object non-exotic for ES5: + * + * module.module bound module object + * module.execute execution function for module + * module.dependencies list of module objects for dependencies + * See getOrCreateModuleRecord for all properties + * + */ + function doExecute(module) { + try { + module.execute.call(__global); + } + catch(e) { + return e; + } + } + + // 15.2.5.5.1 LinkImports not implemented + // 15.2.5.7 ResolveExportEntries not implemented + // 15.2.5.8 ResolveExports not implemented + // 15.2.5.9 ResolveExport not implemented + // 15.2.5.10 ResolveImportEntries not implemented + + // 15.2.6.1 + function evaluateLoadedModule(loader, load) { + console.assert(load.status == 'linked', 'is linked ' + load.name); + + doEnsureEvaluated(load.module, [], loader); + return load.module.module; + } + + // propogate execution errors + // see https://bugs.ecmascript.org/show_bug.cgi?id=2993 + function doEnsureEvaluated(module, seen, loader) { + var err = ensureEvaluated(module, seen, loader); + if (err) + throw err; + } + // 15.2.6.2 EnsureEvaluated adjusted + function ensureEvaluated(module, seen, loader) { + if (module.evaluated || !module.dependencies) + return; + + seen.push(module); + + var deps = module.dependencies; + var err; + + for (var i = 0, l = deps.length; i < l; i++) { + var dep = deps[i]; + // dynamic dependencies are empty in module.dependencies + // as they are already linked + if (!dep) + continue; + if (indexOf.call(seen, dep) == -1) { + err = ensureEvaluated(dep, seen, loader); + // stop on error, see https://bugs.ecmascript.org/show_bug.cgi?id=2996 + if (err) { + err = addToError(err, 'Error evaluating ' + dep.name); + return err; + } + } + } + + if (module.failed) + return new Error('Module failed execution.'); + + if (module.evaluated) + return; + + module.evaluated = true; + err = doExecute(module); + if (err) { + module.failed = true; + } + else if (Object.preventExtensions) { + // spec variation + // we don't create a new module here because it was created and ammended + // we just disable further extensions instead + Object.preventExtensions(module.module); + } + + module.execute = undefined; + return err; + } +})(); + +/* + * Traceur, Babel and TypeScript transpile hook for Loader + */ +var transpile = (function() { + + // use Traceur by default + Loader.prototype.transpiler = 'traceur'; + + function transpile(load) { + var self = this; + + return Promise.resolve(__global[self.transpiler == 'typescript' ? 'ts' : self.transpiler] + || (self.pluginLoader || self)['import'](self.transpiler)) + .then(function(transpiler) { + if (transpiler.__useDefault) + transpiler = transpiler['default']; + + var transpileFunction; + if (transpiler.Compiler) + transpileFunction = traceurTranspile; + else if (transpiler.createLanguageService) + transpileFunction = typescriptTranspile; + else + transpileFunction = babelTranspile; + + // note __moduleName will be part of the transformer meta in future when we have the spec for this + return '(function(__moduleName){' + transpileFunction.call(self, load, transpiler) + '\n})("' + load.name + '");\n//# sourceURL=' + load.address + '!transpiled'; + }); + }; + + function traceurTranspile(load, traceur) { + var options = this.traceurOptions || {}; + options.modules = 'instantiate'; + options.script = false; + if (options.sourceMaps === undefined) + options.sourceMaps = 'inline'; + options.filename = load.address; + options.inputSourceMap = load.metadata.sourceMap; + options.moduleName = false; + + var compiler = new traceur.Compiler(options); + + return doTraceurCompile(load.source, compiler, options.filename); + } + function doTraceurCompile(source, compiler, filename) { + try { + return compiler.compile(source, filename); + } + catch(e) { + // traceur throws an error array + throw e[0]; + } + } + + function babelTranspile(load, babel) { + var options = this.babelOptions || {}; + options.modules = 'system'; + if (options.sourceMap === undefined) + options.sourceMap = 'inline'; + options.inputSourceMap = load.metadata.sourceMap; + options.filename = load.address; + options.code = true; + options.ast = false; + + return babel.transform(load.source, options).code; + } + + function typescriptTranspile(load, ts) { + var options = this.typescriptOptions || {}; + options.target = options.target || ts.ScriptTarget.ES5; + if (options.sourceMap === undefined) + options.sourceMap = true; + if (options.sourceMap && options.inlineSourceMap !== false) + options.inlineSourceMap = true; + + options.module = ts.ModuleKind.System; + + return ts.transpile(load.source, options, load.address); + } + + return transpile; +})(); + +/* +********************************************************************************************* + + System Loader Implementation + + - Implemented to https://github.com/jorendorff/js-loaders/blob/master/browser-loader.js + + - - {% endblock javascript %} - - {% endblock extra_js %} -{% endcomment %} diff --git a/rest_admin/templates/rest_admin/index.html b/rest_admin/templates/rest_admin/index.html index 0eb1d50..20dd787 100644 --- a/rest_admin/templates/rest_admin/index.html +++ b/rest_admin/templates/rest_admin/index.html @@ -3,6 +3,11 @@ {% block extrastyle %}{{ block.super }}{% endblock %} +{% block extrahead %} + + +{% endblock extrahead %} + {% block bodyclass %}{{ block.super }} dashboard{% endblock %} {% block breadcrumbs %}{% endblock %} diff --git a/rest_admin/templates/rest_admin/schema/index.jsx b/rest_admin/templates/rest_admin/schema/index.jsx new file mode 100644 index 0000000..36ff254 --- /dev/null +++ b/rest_admin/templates/rest_admin/schema/index.jsx @@ -0,0 +1,25 @@ +{% load compile_static %} +{% inlinecompile 'browserify' %} +import React from 'react'; +import ReactDOM from 'react-dom'; + +class App extends React.Component { + render() { + return ( +

App goes here

+ ); + } +}; + +const run = (element_id) => { + console.log('Loading to ' + element_id); + var element = document.getElementById(element_id); + ReactDOM.render(, element); + console.log('Loaded to ' + element_id); +} + +console.log('Running!'); +document.addEventListener("DOMContentLoaded", function(event) { + run('content'); +}); +{% endinlinecompile %} diff --git a/test_project/test_project/settings.py b/test_project/test_project/settings.py index cdc59d1..8caff0c 100644 --- a/test_project/test_project/settings.py +++ b/test_project/test_project/settings.py @@ -38,6 +38,7 @@ 'django.contrib.messages', 'django.contrib.staticfiles', + 'static_precompiler', 'rest_framework', 'rest_admin', ) @@ -103,3 +104,18 @@ # https://docs.djangoproject.com/en/1.8/howto/static-files/ STATIC_URL = '/static/' +STATIC_ROOT = os.path.join(BASE_DIR, 'staticfiles') +STATICFILES_FINDERS = [ + # Default: + "django.contrib.staticfiles.finders.FileSystemFinder", + "django.contrib.staticfiles.finders.AppDirectoriesFinder", + + # Static precompiler (for Babel) + 'static_precompiler.finders.StaticPrecompilerFinder', +] +STATIC_PRECOMPILER_COMPILERS = ( + ('static_precompiler.compilers.Browserify', { + # 'executable': '/usr/bin/babel', + 'transform': '[ babelify --presets=es2015,react,stage-0 ]' + }), +)