Support for transpiling .js files (#9160)

* Remove some `.es6` from comments where it does not matter

* Use a post processor for transpilation

This will allow us to eventually use the directory structure to
transpile rather than the extension.

* FIX: Some errors and clean up in confirm-new-email

It would throw an error if the webauthn element wasn't present.
Also I changed things so that no-module is not explicitly
referenced.

* Remove `no-module`

Instead we allow a magic comment: `// discourse-skip-module` to prevent
the asset pipeline from creating a module.

* DEV: Enable babel transpilation based on directory

If it's in `app/assets/javascripts/dicourse` it will be transpiled
even without the `.es6` extension.

* REFACTOR: Remove Tilt/ES6ModuleTranspiler
This commit is contained in:
Robin Ward 2020-03-11 09:43:55 -04:00 committed by GitHub
parent fd4ce6ab8f
commit a3f0543f99
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
38 changed files with 152 additions and 265 deletions

View File

@ -3,7 +3,7 @@ app/assets/javascripts/main_include_admin.js
app/assets/javascripts/vendor.js app/assets/javascripts/vendor.js
app/assets/javascripts/locales/i18n.js app/assets/javascripts/locales/i18n.js
app/assets/javascripts/ember-addons/ app/assets/javascripts/ember-addons/
app/assets/javascripts/discourse/lib/autosize.js.es6 app/assets/javascripts/discourse/lib/autosize.js
lib/javascripts/locale/ lib/javascripts/locale/
lib/javascripts/messageformat.js lib/javascripts/messageformat.js
lib/highlight_js/ lib/highlight_js/

View File

@ -120,9 +120,6 @@ gem 'sanitize'
gem 'sidekiq' gem 'sidekiq'
gem 'mini_scheduler' gem 'mini_scheduler'
# for sidekiq web
gem 'tilt', require: false
gem 'execjs', require: false gem 'execjs', require: false
gem 'mini_racer' gem 'mini_racer'

View File

@ -539,7 +539,6 @@ DEPENDENCIES
stackprof stackprof
test-prof test-prof
thor thor
tilt
uglifier uglifier
unf unf
unicorn unicorn

View File

@ -1,3 +1,4 @@
// discourse-skip-module
(function() { (function() {
setTimeout(function() { setTimeout(function() {
const $activateButton = $("#activate-account-button"); const $activateButton = $("#activate-account-button");

View File

@ -1,3 +1,4 @@
// discourse-skip-module
(function() { (function() {
const path = document.getElementById("data-auto-redirect").dataset.path; const path = document.getElementById("data-auto-redirect").dataset.path;
setTimeout(function() { setTimeout(function() {

View File

@ -0,0 +1,4 @@
// discourse-skip-module
(function() {
require("confirm-new-email/confirm-new-email");
})();

View File

@ -1,6 +1,8 @@
import { getWebauthnCredential } from "discourse/lib/webauthn"; import { getWebauthnCredential } from "discourse/lib/webauthn";
document.getElementById("submit-security-key").onclick = function(e) { const security = document.getElementById("submit-security-key");
if (security) {
security.onclick = function(e) {
e.preventDefault(); e.preventDefault();
getWebauthnCredential( getWebauthnCredential(
document.getElementById("security-key-challenge").value, document.getElementById("security-key-challenge").value,
@ -8,9 +10,9 @@ document.getElementById("submit-security-key").onclick = function(e) {
.getElementById("security-key-allowed-credential-ids") .getElementById("security-key-allowed-credential-ids")
.value.split(","), .value.split(","),
credentialData => { credentialData => {
document.getElementById("security-key-credential").value = JSON.stringify( document.getElementById(
credentialData "security-key-credential"
); ).value = JSON.stringify(credentialData);
$(e.target) $(e.target)
.parents("form") .parents("form")
@ -20,4 +22,5 @@ document.getElementById("submit-security-key").onclick = function(e) {
document.getElementById("security-key-error").innerText = errorMessage; document.getElementById("security-key-error").innerText = errorMessage;
} }
); );
}; };
}

View File

@ -1 +0,0 @@
require("confirm-new-email/confirm-new-email").default();

View File

@ -6,7 +6,7 @@ import {
isWebauthnSupported isWebauthnSupported
} from "discourse/lib/webauthn"; } from "discourse/lib/webauthn";
// model for this controller is user.js.es6 // model for this controller is user
export default Controller.extend(ModalFunctionality, { export default Controller.extend(ModalFunctionality, {
loading: false, loading: false,
errorMessage: null, errorMessage: null,

View File

@ -848,7 +848,7 @@ class PluginApi {
* *
* Example: * Example:
* *
* // read /discourse/lib/sharing.js.es6 for options * // read discourse/lib/sharing for options
* api.addSharingSource(options) * api.addSharingSource(options)
* *
*/ */

View File

@ -12,7 +12,7 @@ export function resetExtraClasses() {
} }
// Note: In plugins, define a class by path and it will be wired up automatically // Note: In plugins, define a class by path and it will be wired up automatically
// eg: discourse/connectors/<OUTLET NAME>/<CONNECTOR NAME>.js.es6 // eg: discourse/connectors/<OUTLET NAME>/<CONNECTOR NAME>
export function extraConnectorClass(name, obj) { export function extraConnectorClass(name, obj) {
_extraConnectorClasses[name] = obj; _extraConnectorClasses[name] = obj;
} }

View File

@ -1,3 +1,4 @@
// discourse-skip-module
(function() { (function() {
const referer = document.getElementById("data-embedded").dataset.referer; const referer = document.getElementById("data-embedded").dataset.referer;

View File

@ -1,3 +1,4 @@
// discourse-skip-module
(function() { (function() {
const gtmDataElement = document.getElementById("data-google-tag-manager"); const gtmDataElement = document.getElementById("data-google-tag-manager");
const dataLayerJson = JSON.parse(gtmDataElement.dataset.dataLayer); const dataLayerJson = JSON.parse(gtmDataElement.dataset.dataLayer);

View File

@ -1,3 +1,4 @@
// discourse-skip-module
/* eslint-disable */ /* eslint-disable */
// prettier-ignore // prettier-ignore
(function(i,s,o,g,r,a,m){i['GoogleAnalyticsObject']=r;i[r]=i[r]||function(){ (function(i,s,o,g,r,a,m){i['GoogleAnalyticsObject']=r;i[r]=i[r]||function(){

View File

@ -1,3 +1,4 @@
// discourse-skip-module
window.onpopstate = function(event) { window.onpopstate = function(event) {
// check if Discourse object exists if not take care of back navigation // check if Discourse object exists if not take care of back navigation
if (event.state && !window.hasOwnProperty("Discourse")) { if (event.state && !window.hasOwnProperty("Discourse")) {

View File

@ -1,3 +1,4 @@
// discourse-skip-module
(function() { (function() {
var ps = require("preload-store").default; var ps = require("preload-store").default;
var preloadedDataElement = document.getElementById("data-preloaded"); var preloadedDataElement = document.getElementById("data-preloaded");
@ -55,6 +56,7 @@
Discourse.S3BaseUrl = setupData.s3BaseUrl; Discourse.S3BaseUrl = setupData.s3BaseUrl;
} }
// eslint-disable-next-line
Ember.RSVP.configure("onerror", function(e) { Ember.RSVP.configure("onerror", function(e) {
// Ignore TransitionAborted exceptions that bubble up // Ignore TransitionAborted exceptions that bubble up
if (e && e.message === "TransitionAborted") { if (e && e.message === "TransitionAborted") {

View File

@ -1,3 +1,4 @@
// discourse-skip-module
(function() { (function() {
var wizard = require("wizard/wizard").default.create(); var wizard = require("wizard/wizard").default.create();
wizard.start(); wizard.start();

View File

@ -78,5 +78,5 @@
<%= preload_script "locales/i18n" %> <%= preload_script "locales/i18n" %>
<%= preload_script "discourse/lib/webauthn" %> <%= preload_script "discourse/lib/webauthn" %>
<%= preload_script "confirm-new-email/confirm-new-email" %> <%= preload_script "confirm-new-email/confirm-new-email" %>
<%= preload_script "confirm-new-email/confirm-new-email.no-module" %> <%= preload_script "confirm-new-email/bootstrap" %>
</div> </div>

View File

@ -76,7 +76,6 @@ module Discourse
# confused here if we load the deps without `lib` it thinks # confused here if we load the deps without `lib` it thinks
# discourse.rb is under the discourse folder incorrectly # discourse.rb is under the discourse folder incorrectly
require_dependency 'lib/discourse' require_dependency 'lib/discourse'
require_dependency 'lib/es6_module_transpiler/rails'
require_dependency 'lib/js_locale_helper' require_dependency 'lib/js_locale_helper'
# tiny file needed by site settings # tiny file needed by site settings
@ -155,7 +154,7 @@ module Discourse
locales/i18n.js locales/i18n.js
discourse/lib/webauthn.js discourse/lib/webauthn.js
confirm-new-email/confirm-new-email.js confirm-new-email/confirm-new-email.js
confirm-new-email/confirm-new-email.no-module.js confirm-new-email/bootstrap.js
onpopstate-handler.js onpopstate-handler.js
embed-application.js embed-application.js
} }
@ -244,6 +243,11 @@ module Discourse
Sprockets.register_mime_type 'text/x-handlebars', extensions: ['.hbr'] Sprockets.register_mime_type 'text/x-handlebars', extensions: ['.hbr']
Sprockets.register_transformer 'text/x-handlebars', 'application/javascript', Ember::Handlebars::Template Sprockets.register_transformer 'text/x-handlebars', 'application/javascript', Ember::Handlebars::Template
require 'discourse_js_processor'
Sprockets.register_mime_type 'application/javascript', extensions: ['.js', '.es6', '.js.es6'], charset: :unicode
Sprockets.register_postprocessor 'application/javascript', DiscourseJsProcessor
require 'discourse_redis' require 'discourse_redis'
require 'logster/redis_store' require 'logster/redis_store'
# Use redis for our cache # Use redis for our cache

View File

@ -1,12 +0,0 @@
# frozen_string_literal: true
require 'discourse_iife'
Rails.application.config.assets.configure do |env|
env.register_preprocessor('application/javascript', DiscourseIIFE)
unless Rails.env.production?
require 'source_url'
env.register_postprocessor('application/javascript', SourceURL)
end
end

View File

@ -655,7 +655,7 @@ module Discourse
# in case v8 was initialized we want to make sure it is nil # in case v8 was initialized we want to make sure it is nil
PrettyText.reset_context PrettyText.reset_context
Tilt::ES6ModuleTranspilerTemplate.reset_context if defined? Tilt::ES6ModuleTranspilerTemplate DiscourseJsProcessor::Transpiler.reset_context if defined? DiscourseJsProcessor::Transpiler
JsLocaleHelper.reset_context if defined? JsLocaleHelper JsLocaleHelper.reset_context if defined? JsLocaleHelper
nil nil
end end

View File

@ -1,45 +0,0 @@
# frozen_string_literal: true
class DiscourseIIFE
def initialize(options = {}, &block)
end
def self.instance
@instance ||= new
end
def self.call(input)
instance.call(input)
end
# Add a IIFE around our javascript
def call(input)
path = input[:environment].context_class.new(input).pathname.to_s
data = input[:data]
# Only discourse or admin paths
return data unless (path =~ /\/javascripts\/discourse/ || path =~ /\/javascripts\/admin/ || path =~ /\/test\/javascripts/)
# Ignore the js helpers
return data if (path =~ /test\_helper\.js/)
return data if (path =~ /javascripts\/helpers\//)
# Ignore ES6 files
return data if (path =~ /\.es6/)
# Ignore translations
return data if (path =~ /\/translations/)
# We don't add IIFEs to handlebars
return data if path =~ /\.handlebars/
return data if path =~ /\.shbrs/
return data if path =~ /\.hbrs/
return data if path =~ /\.hbs/
return data if path =~ /\.hbr/
return data if path =~ /discourse-loader/
"(function () {\n\nvar $ = window.jQuery;\n// IIFE Wrapped Content Begins:\n\n#{data}\n\n// IIFE Wrapped Content Ends\n\n })(this);"
end
end

View File

@ -1,28 +1,54 @@
# frozen_string_literal: true # frozen_string_literal: true
require 'execjs' require 'execjs'
require 'mini_racer' require 'mini_racer'
module Tilt class DiscourseJsProcessor
class ES6ModuleTranspilerTemplate < Tilt::Template def self.call(input)
self.default_mime_type = 'application/javascript' root_path = input[:load_path] || ''
logical_path = (input[:filename] || '').sub(root_path, '').gsub(/\.(js|es6).*$/, '').sub(/^\//, '')
data = input[:data]
if should_transpile?(input[:filename])
data = transpile(data, root_path, logical_path)
end
# add sourceURL until we can do proper source maps
unless Rails.env.production?
data = "eval(#{data.inspect} + \"\\n//# sourceURL=#{logical_path}\");\n"
end
{ data: data }
end
def self.transpile(data, root_path, logical_path)
transpiler = Transpiler.new(skip_module: skip_module?(data))
transpiler.perform(data, root_path, logical_path)
end
def self.should_transpile?(filename)
filename ||= ''
# es6 is always transpiled
return true if filename.end_with?(".es6") || filename.end_with?(".es6.erb")
# For .js check the path...
return false unless filename.end_with?(".js") || filename.end_with?(".js.erb")
relative_path = filename.sub(Rails.root.to_s, '').sub(/^\/*/, '')
relative_path.start_with?("app/assets/javascripts/discourse/")
end
def self.skip_module?(data)
!!(data.present? && data =~ /^\/\/ discourse-skip-module$/)
end
class Transpiler
@mutex = Mutex.new @mutex = Mutex.new
@ctx_init = Mutex.new @ctx_init = Mutex.new
def self.call(input) def self.mutex
filename = input[:filename] @mutex
source = input[:data]
context = input[:environment].context_class.new(input)
result = new(filename) { source }.render(context)
context.metadata.merge(data: result)
end
def prepare
# intentionally left empty
# Tilt requires this method to be defined
end end
def self.create_new_context def self.create_new_context
@ -66,33 +92,13 @@ JS
@ctx @ctx
end end
class JavaScriptError < StandardError def initialize(skip_module: false)
attr_accessor :message, :backtrace @skip_module = skip_module
def initialize(message, backtrace)
@message = message
@backtrace = backtrace
end end
end def perform(source, root_path = nil, logical_path = nil)
def self.protect
@mutex.synchronize do
yield
end
end
def babel_transpile(source)
klass = self.class klass = self.class
klass.protect do klass.mutex.synchronize do
klass.v8.eval("console.prefix = 'BABEL: babel-eval: ';")
@output = klass.v8.eval(babel_source(source))
end
end
def module_transpile(source, root_path, logical_path)
klass = self.class
klass.protect do
klass.v8.eval("console.prefix = 'BABEL: babel-eval: ';") klass.v8.eval("console.prefix = 'BABEL: babel-eval: ';")
transpiled = babel_source( transpiled = babel_source(
source, source,
@ -103,31 +109,12 @@ JS
end end
end end
def evaluate(scope, locals, &block)
return @output if @output
klass = self.class
klass.protect do
klass.v8.eval("console.prefix = 'BABEL: #{scope.logical_path}: ';")
source = babel_source(
data,
module_name: module_name(scope.root_path, scope.logical_path),
filename: scope.logical_path
)
@output = klass.v8.eval(source)
end
@output
end
def babel_source(source, opts = nil) def babel_source(source, opts = nil)
opts ||= {} opts ||= {}
js_source = ::JSON.generate(source, quirks_mode: true) js_source = ::JSON.generate(source, quirks_mode: true)
if opts[:module_name] && transpile_into_module? if opts[:module_name] && !@skip_module
filename = opts[:filename] || 'unknown' filename = opts[:filename] || 'unknown'
"Babel.transform(#{js_source}, { moduleId: '#{opts[:module_name]}', filename: '#{filename}', ast: false, presets: ['es2015'], plugins: [['transform-es2015-modules-amd', {noInterop: true}], 'transform-decorators-legacy', exports.WidgetHbsCompiler] }).code" "Babel.transform(#{js_source}, { moduleId: '#{opts[:module_name]}', filename: '#{filename}', ast: false, presets: ['es2015'], plugins: [['transform-es2015-modules-amd', {noInterop: true}], 'transform-decorators-legacy', exports.WidgetHbsCompiler] }).code"
else else
@ -135,12 +122,6 @@ JS
end end
end end
private
def transpile_into_module?
file.nil? || file.exclude?('.no-module')
end
def module_name(root_path, logical_path) def module_name(root_path, logical_path)
path = nil path = nil
@ -153,26 +134,8 @@ JS
path = "discourse/plugins/#{plugin.name}/#{logical_path.sub(/javascripts\//, '')}" if plugin path = "discourse/plugins/#{plugin.name}/#{logical_path.sub(/javascripts\//, '')}" if plugin
end end
path ||= logical_path path || logical_path
if ES6ModuleTranspiler.transform
path = ES6ModuleTranspiler.transform.call(path)
end end
path
end
def compiler_method
type = {
amd: 'AMD',
cjs: 'CJS',
globals: 'Globals'
}[ES6ModuleTranspiler.compile_to.to_sym]
"to#{type}"
end
def compiler_options
::JSON.generate(ES6ModuleTranspiler.compiler_options, quirks_mode: true)
end
end end
end end

View File

@ -151,7 +151,7 @@ class DiscoursePluginRegistry
end end
end end
JS_REGEX = /\.js$|\.js\.erb$|\.js\.es6|\.js\.no-module\.es6$/ JS_REGEX = /\.js$|\.js\.erb$|\.js\.es6$/
HANDLEBARS_REGEX = /\.(hb[rs]|js\.handlebars)$/ HANDLEBARS_REGEX = /\.(hb[rs]|js\.handlebars)$/
def self.register_asset(asset, opts = nil, plugin_directory_name = nil) def self.register_asset(asset, opts = nil, plugin_directory_name = nil)

View File

@ -1,27 +0,0 @@
# frozen_string_literal: true
require 'es6_module_transpiler/rails/version'
require 'es6_module_transpiler/tilt'
require 'es6_module_transpiler/sprockets'
module ES6ModuleTranspiler
def self.compile_to
@compile_to || :amd
end
def self.compile_to=(target)
@compile_to = target
end
def self.transform=(transform)
@transform = transform
end
def self.transform
@transform
end
def self.compiler_options
@compiler_options ||= {}
end
end

View File

@ -1,7 +0,0 @@
# frozen_string_literal: true
module ES6ModuleTranspiler
module Rails
VERSION = '0.4.0'
end
end

View File

@ -1,6 +0,0 @@
# frozen_string_literal: true
require 'sprockets'
Sprockets.register_mime_type 'application/ecmascript6', extensions: ['.es6', '.js.es6', '.js.no-module.es6'], charset: :unicode
Sprockets.register_transformer 'application/ecmascript6', 'application/javascript', Tilt::ES6ModuleTranspilerTemplate

View File

@ -1,6 +0,0 @@
# frozen_string_literal: true
require 'tilt'
require 'es6_module_transpiler/tilt/es6_module_transpiler_template'
Tilt.register Tilt::ES6ModuleTranspilerTemplate, 'es6'

View File

@ -12,8 +12,8 @@ class Barber::Precompiler
if !@precompiler if !@precompiler
source = File.read("#{Rails.root}/app/assets/javascripts/discourse-common/lib/raw-handlebars.js.es6") source = File.read("#{Rails.root}/app/assets/javascripts/discourse-common/lib/raw-handlebars.js.es6")
template = Tilt::ES6ModuleTranspilerTemplate.new {} transpiler = DiscourseJsProcessor::Transpiler.new(skip_module: true)
transpiled = template.babel_transpile(source) transpiled = transpiler.perform(source)
# very hacky but lets us use ES6. I'm ashamed of this code -RW # very hacky but lets us use ES6. I'm ashamed of this code -RW
transpiled = transpiled[0...transpiled.index('export ')] transpiled = transpiled[0...transpiled.index('export ')]

View File

@ -12,7 +12,6 @@ module ActiveSupport::Dependencies::ZeitwerkIntegration::Inflector
'postgresql_fallback_adapter' => 'PostgreSQLFallbackHandler', 'postgresql_fallback_adapter' => 'PostgreSQLFallbackHandler',
'regular' => 'Jobs', 'regular' => 'Jobs',
'scheduled' => 'Jobs', 'scheduled' => 'Jobs',
'source_url' => 'SourceURL',
'topic_query_sql' => 'TopicQuerySQL', 'topic_query_sql' => 'TopicQuerySQL',
'version' => 'Discourse', 'version' => 'Discourse',
} }

View File

@ -29,13 +29,10 @@ module PrettyText
filename = find_file(root_path, part_name) filename = find_file(root_path, part_name)
if filename if filename
source = File.read("#{root_path}#{filename}") source = File.read("#{root_path}#{filename}")
source = ERB.new(source).result(binding) if filename =~ /\.erb$/
if filename =~ /\.erb$/ transpiler = DiscourseJsProcessor::Transpiler.new
source = ERB.new(source).result(binding) transpiled = transpiler.perform(source, "#{Rails.root}/app/assets/javascripts/", part_name)
end
template = Tilt::ES6ModuleTranspilerTemplate.new {}
transpiled = template.module_transpile(source, "#{Rails.root}/app/assets/javascripts/", part_name)
ctx.eval(transpiled) ctx.eval(transpiled)
else else
# Look for vendored stuff # Look for vendored stuff

View File

@ -1,24 +0,0 @@
# frozen_string_literal: true
class SourceURL < Tilt::Template
self.default_mime_type = 'application/javascript'
def self.call(input)
filename = input[:filename]
source = input[:data]
context = input[:environment].context_class.new(input)
result = new(filename) { source }.render(context)
context.metadata.merge(data: result)
end
def prepare
end
def evaluate(scope, locals, &block)
code = +"eval("
code << data.inspect
code << " + \"\\n//# sourceURL=#{scope.logical_path}\""
code << ");\n"
end
end

View File

@ -214,8 +214,8 @@ class ThemeJavascriptCompiler
def append_module(script, name, include_variables: true) def append_module(script, name, include_variables: true)
script = "#{theme_variables}#{script}" if include_variables script = "#{theme_variables}#{script}" if include_variables
template = Tilt::ES6ModuleTranspilerTemplate.new {} transpiler = DiscourseJsProcessor::Transpiler.new
@content << template.module_transpile(script, "", name) @content << transpiler.perform(script, "", name)
rescue MiniRacer::RuntimeError => ex rescue MiniRacer::RuntimeError => ex
raise CompileError.new ex.message raise CompileError.new ex.message
end end
@ -237,7 +237,7 @@ class ThemeJavascriptCompiler
end end
def transpile(es6_source, version) def transpile(es6_source, version)
template = Tilt::ES6ModuleTranspilerTemplate.new {} transpiler = DiscourseJsProcessor::Transpiler.new(skip_module: true)
wrapped = <<~PLUGIN_API_JS wrapped = <<~PLUGIN_API_JS
(function() { (function() {
if ('Discourse' in window && typeof Discourse._registerPluginCode === 'function') { if ('Discourse' in window && typeof Discourse._registerPluginCode === 'function') {
@ -254,7 +254,7 @@ class ThemeJavascriptCompiler
})(); })();
PLUGIN_API_JS PLUGIN_API_JS
template.babel_transpile(wrapped) transpiler.perform(wrapped)
rescue MiniRacer::RuntimeError => ex rescue MiniRacer::RuntimeError => ex
raise CompileError.new ex.message raise CompileError.new ex.message
end end

View File

@ -1,3 +1,4 @@
// discourse-skip-module
(function($) { (function($) {
const DATE_TEMPLATE = ` const DATE_TEMPLATE = `
<span> <span>

View File

@ -6,7 +6,7 @@
# author: Joffrey Jaffeux # author: Joffrey Jaffeux
hide_plugin if self.respond_to?(:hide_plugin) hide_plugin if self.respond_to?(:hide_plugin)
register_asset 'javascripts/discourse-local-dates.js.no-module.es6' register_asset 'javascripts/discourse-local-dates.js.es6'
register_asset 'stylesheets/common/discourse-local-dates.scss' register_asset 'stylesheets/common/discourse-local-dates.scss'
register_asset 'moment.js', :vendored_core_pretty_text register_asset 'moment.js', :vendored_core_pretty_text
register_asset 'moment-timezone.js', :vendored_core_pretty_text register_asset 'moment-timezone.js', :vendored_core_pretty_text

View File

@ -0,0 +1,39 @@
# frozen_string_literal: true
require 'rails_helper'
require 'discourse_js_processor'
describe DiscourseJsProcessor do
describe 'should_transpile?' do
it "returns false for empty strings" do
expect(DiscourseJsProcessor.should_transpile?(nil)).to eq(false)
expect(DiscourseJsProcessor.should_transpile?('')).to eq(false)
end
it "returns false for a regular js file" do
expect(DiscourseJsProcessor.should_transpile?("file.js")).to eq(false)
end
it "returns true for deprecated .es6 files" do
expect(DiscourseJsProcessor.should_transpile?("file.es6")).to eq(true)
expect(DiscourseJsProcessor.should_transpile?("file.js.es6")).to eq(true)
expect(DiscourseJsProcessor.should_transpile?("file.js.es6.erb")).to eq(true)
end
end
describe "skip_module?" do
it "returns false for empty strings" do
expect(DiscourseJsProcessor.skip_module?(nil)).to eq(false)
expect(DiscourseJsProcessor.skip_module?('')).to eq(false)
end
it "returns true if the header is present" do
expect(DiscourseJsProcessor.skip_module?("// cool comment\n// discourse-skip-module")).to eq(true)
end
it "returns false if the header is not present" do
expect(DiscourseJsProcessor.skip_module?("// just some JS\nconsole.log()")).to eq(false)
end
end
end