From 19d44a55622dd59f95cc3ef74c01e5fb595455d5 Mon Sep 17 00:00:00 2001 From: Shane Osbourne Date: Sat, 27 Oct 2018 09:51:53 +0100 Subject: [PATCH] fix: parse the entire requirejs-config.js file - fixes #32 --- src/lib/presets/m2/handlers/config_capture.rs | 20 +- src/lib/presets/m2/parse.rs | 513 +++++++++---- src/lib/presets/m2/requirejs_config.rs | 80 +-- src/lib/presets/m2/static/post_config.js | 14 - test/fixtures/rjs-config-expected.json | 234 ++++++ test/fixtures/rjs-config.js | 672 ++++++++++++++++++ 6 files changed, 1329 insertions(+), 204 deletions(-) delete mode 100644 src/lib/presets/m2/static/post_config.js create mode 100644 test/fixtures/rjs-config-expected.json create mode 100644 test/fixtures/rjs-config.js diff --git a/src/lib/presets/m2/handlers/config_capture.rs b/src/lib/presets/m2/handlers/config_capture.rs index b61c440..dd38af5 100644 --- a/src/lib/presets/m2/handlers/config_capture.rs +++ b/src/lib/presets/m2/handlers/config_capture.rs @@ -1,29 +1,23 @@ use actix_web::HttpRequest; use app_state::AppState; -use presets::m2::parse::get_deps_from_str; use presets::m2::preset_m2::FutResp; +use presets::m2::requirejs_config::RequireJsClientConfig; use proxy_utils::apply_to_proxy_body; /// -/// This handler has 2 purposes. -/// -/// First, it will record the incoming string from the Magento-generated +/// This handler will record the incoming string from the Magento-generated /// requirejs-config.js and use that to build up the 'deps' array. This is required /// since the client config that the client posts back does not include all original /// 'deps' (I'm not sure why) /// -/// Secondly, it will append a small piece of JS to the end of the file in order -/// to send back the configuration. -/// pub fn handle(original_request: &HttpRequest) -> FutResp { let client_config_clone = original_request.state().rjs_client_config.clone(); - apply_to_proxy_body(&original_request, move |mut b| { + apply_to_proxy_body(&original_request, move |b| { let c2 = client_config_clone.clone(); - if let Ok(deps) = get_deps_from_str(&b) { - let mut w = c2.lock().expect("unwraped"); - w.deps = deps; - }; - b.push_str(include_str!("../static/post_config.js")); + if let Ok(rjs) = RequireJsClientConfig::from_generated_string(b.to_string()) { + let mut w = c2.lock().expect("unwrapped client_config_clone"); + *w = rjs + } b }) } diff --git a/src/lib/presets/m2/parse.rs b/src/lib/presets/m2/parse.rs index b8d8bd5..a207d41 100644 --- a/src/lib/presets/m2/parse.rs +++ b/src/lib/presets/m2/parse.rs @@ -1,141 +1,69 @@ -use ratel::error::ParseError; use ratel::grammar::Expression; use ratel::grammar::*; use ratel::grammar::{ObjectKey, ObjectMember, Value}; +use ratel::owned_slice::OwnedSlice; use ratel::parser::parse; +use serde_json; +use std::collections::HashMap; -/// -/// Parse a Magento 2 generated requirejs-config.js file -/// to pull out the top-level 'deps' arrays -/// -/// # Examples -/// -/// ``` -/// # use bs::presets::m2::parse::*; -/// let input = r#" -/// (function() { -/// var config = { -/// deps: ["one", "two"] -/// }; -/// require.config(config); -/// })(); -/// "#; -/// let deps = get_deps_from_str(input).unwrap(); -/// assert_eq!(deps, vec!["one".to_string(), "two".to_string()]); -/// ``` -/// -/// -pub fn get_deps_from_str(input: &str) -> Result, ParseError> { - let out = parse(input.into())?; - let mut deps: Vec = vec![]; - parse_body(out.body, &mut deps); - Ok(deps) +#[derive(Serialize, Deserialize, Debug, Default, PartialEq)] +pub struct ParsedConfig { + pub paths: HashMap, + pub map: HashMap>, + pub deps: Vec, + pub config: HashMap>>, + pub shim: HashMap>, } -fn test_get_deps_from_str() { - let input = r#" - (function() { - /** - * Copyright © Magento, Inc. All rights reserved. - * See COPYING.txt for license details. - */ - - var config = { - map: { - '*': { - checkoutBalance: 'Magento_Customer/js/checkout-balance', - address: 'Magento_Customer/address', - changeEmailPassword: 'Magento_Customer/change-email-password', - passwordStrengthIndicator: 'Magento_Customer/js/password-strength-indicator', - zxcvbn: 'Magento_Customer/js/zxcvbn', - addressValidation: 'Magento_Customer/js/addressValidation' - } - }, - deps: ["first", "second"] - }; - - require.config(config); - })(); - (function() { - var config = { - deps: ["third", "forth"] - }; - require.config(config); - })(); - (function() { - var config = { - 'deps': [ - 'jquery/jquery-single' - ], - }; - require.config(config); - })(); - (function() { - var config = { - "deps": [ - 'jquery/jquery-double' - ], - }; - require.config(config); - })(); - "#; - - let deps = get_deps_from_str(input).unwrap(); - assert_eq!( - deps, - vec![ - "first".to_string(), - "second".to_string(), - "third".to_string(), - "forth".to_string(), - "jquery/jquery-single".to_string(), - "jquery/jquery-double".to_string(), - ] - ); +#[derive(Debug)] +pub enum OutputError { + ParseJs, + Serialize, + Conversion, } -#[test] -fn test_from_large_file() { - let input = include_str!("../../../../test/fixtures/requirejs-config-generated.js"); - let deps = get_deps_from_str(input).unwrap(); - - assert_eq!( - deps, - vec![ - "jquery/jquery.mobile.custom", - "mage/common", - "mage/dataPost", - "mage/bootstrap", - "jquery/jquery-migrate", - "mage/translate-inline", - "Magento_Theme/js/responsive", - "Magento_Theme/js/theme", - ] - ); +impl ParsedConfig { + /// + /// Parse a Magento 2 generated requirejs-config.js file pulling out + /// only the pieces of 'config' and ignoring any actual JS + /// + /// # Examples + /// + /// ``` + /// # use bs::presets::m2::parse::*; + /// let input = r#" + /// (function() { + /// var config = { + /// deps: ["one", "two"] + /// }; + /// require.config(config); + /// })(); + /// "#; + /// let rjs_cfg = ParsedConfig::from_str(input).expect("should parse"); + /// assert_eq!(rjs_cfg.deps, vec!["one".to_string(), "two".to_string()]); + /// ``` + /// + pub fn from_str(input: impl Into) -> Result { + let mut o = ParsedConfig { + ..ParsedConfig::default() + }; + let parsed = parse(input.into()).map_err(|_e| OutputError::ParseJs)?; + parse_body(parsed.body, &mut o); + Ok(o) + } } -fn parse_body(items: Vec, deps: &mut Vec) { +fn parse_body(items: Vec, output: &mut ParsedConfig) { for statement in items.iter() { match statement { Statement::VariableDeclaration { declarators, .. } => { for d in declarators.iter().filter(|d| d.name.as_str() == "config") { - match d.value { - Some(Expression::Object(ref xs)) => { - if let Some(Expression::Array(vs)) = get_object_value(&xs, "deps") { - for v in vs { - match v { - Expression::Literal(Value::String(s)) => { - let len = s.len(); - let next_s = &s[1..len - 1]; - deps.push(next_s.to_string()); - } - _ => { /* */ } - } - } - } - } - Some(_) => { /* */ } - None => { /* */ } + if let Some(Expression::Object(ref xs)) = d.value { + process_deps(&xs, output); + process_map(&xs, output); + process_paths(&xs, output); + process_config(&xs, output); + process_shim(&xs, output); } } } @@ -145,7 +73,7 @@ fn parse_body(items: Vec, deps: &mut Vec) { let fun = (**callee).clone(); match fun { Expression::Function { body, .. } => { - parse_body(body, deps); + parse_body(body, output); } _ => { /* */ } } @@ -158,9 +86,218 @@ fn parse_body(items: Vec, deps: &mut Vec) { } } +fn process_shim(xs: &Vec, output: &mut ParsedConfig) { + match get_object_value(&xs, "shim") { + Some(Expression::Object(vs)) => { + for v in vs { + match v { + ObjectMember::Value { + key: ObjectKey::Literal(s), + value, + } => { + let mut map_item = output + .shim + .entry(strip_literal(s)) + .or_insert(HashMap::new()); + match value { + Expression::Object(vs) => { + for v in vs { + match v { + ObjectMember::Value { + key: ObjectKey::Literal(k), + value: Expression::Literal(Value::String(v)), + } => { + map_item.insert( + strip_literal(k), + serde_json::Value::String( + strip_literal(v).to_string(), + ), + ); + } + ObjectMember::Value { + key: ObjectKey::Literal(k), + value: Expression::Array(items), + } => { + let as_serde: Vec = items + .into_iter() + .filter_map(|e: Expression| { + match e { + Expression::Literal(Value::String(s)) => { + Some(strip_literal(s).to_string()) + } + _ => None + } + }) + .map(|s| serde_json::Value::String(s)) + .collect(); + map_item.insert( + strip_literal(k), + serde_json::Value::Array(as_serde), + ); + } + _ => {} + } + } + } + _ => { /* */ } + } + } + _a => println!("s={:?}", _a), + } + } + } + _ => { /* */ } + } +} +fn process_config(xs: &Vec, output: &mut ParsedConfig) { + match get_object_value(&xs, "config") { + Some(Expression::Object(vs)) => { + for v in vs { + match v { + ObjectMember::Value { + key: ObjectKey::Literal(s), + value, + } => { + let mut map_item = + output.config.entry(s.to_string()).or_insert(HashMap::new()); + + match value { + Expression::Object(vs) => { + for v in vs { + match v { + ObjectMember::Value { + key: ObjectKey::Literal(k), + value: Expression::Object(vs), + } => { + let mut inner_map_item = map_item + .entry(strip_literal(k)) + .or_insert(HashMap::new()); + + for v in vs { + match v { + ObjectMember::Value { + key: ObjectKey::Literal(k), + value, + } => match value { + Expression::Literal(Value::True) => { + inner_map_item.insert( + strip_literal(k), + serde_json::Value::Bool(true), + ); + } + _ => { + inner_map_item.insert( + strip_literal(k), + json!({}), + ); + } + }, + _ => { /* */ } + } + } + } + _ => { /* */ } + } + } + } + _ => { /* */ } + }; + } + _ => { /* */ } + }; + } + } + _ => { /* */ } + }; +} +fn process_paths(xs: &Vec, output: &mut ParsedConfig) { + match get_object_value(&xs, "paths") { + Some(Expression::Object(vs)) => { + for v in vs { + match v { + ObjectMember::Value { + key: ObjectKey::Literal(k), + value: Expression::Literal(Value::String(v)), + } => { + output.paths.insert(strip_literal(k), strip_literal(v)); + } + _ => { /* */ } + }; + } + } + _ => { /* */ } + }; +} + +fn process_deps(xs: &Vec, output: &mut ParsedConfig) { + match get_object_value(&xs, "deps") { + Some(Expression::Array(vs)) => { + for v in vs { + match v { + Expression::Literal(Value::String(s)) => { + let len = s.len(); + let next_s = &s[1..len - 1]; + output.deps.push(next_s.to_string()); + } + _ => { /* */ } + } + } + } + _ => { /* */ } + }; +} + +fn process_map(xs: &Vec, output: &mut ParsedConfig) { + match get_object_value(&xs, "map") { + Some(Expression::Object(vs)) => { + for v in vs { + match v { + ObjectMember::Value { + key: ObjectKey::Literal(s), + value, + } => { + let mut map_item = + output.map.entry(strip_literal(s)).or_insert(HashMap::new()); + + match value { + Expression::Object(vs) => { + for v in vs { + match v { + ObjectMember::Value { + key: ObjectKey::Literal(k), + value: Expression::Literal(Value::String(v)), + } => { + map_item.insert(k.to_string(), strip_literal(v)); + } + _ => { /* */ } + } + } + } + _ => { /* */ } + }; + } + _ => { /* */ } + }; + } + } + _ => { /* */ } + }; +} + +fn strip_literal(o: OwnedSlice) -> String { + match &o[0..1] { + "\"" | "'" => { + let len = o.len(); + let next_key = &o[1..len - 1]; + next_key.to_string() + } + _ => o.to_string(), + } +} + fn get_object_value(xs: &Vec, name: &str) -> Option { xs.iter() - .find(|x| filter_deps(*x, name)) + .find(|x| filter_items(*x, name)) .and_then(|x| match x { ObjectMember::Value { value, .. } => Some(value.clone()), _ => None, @@ -168,7 +305,7 @@ fn get_object_value(xs: &Vec, name: &str) -> Option { .or(None) } -fn filter_deps(x: &ObjectMember, name: &str) -> bool { +fn filter_items(x: &ObjectMember, name: &str) -> bool { match x { ObjectMember::Value { key, .. } => match key { ObjectKey::Literal(s) => { @@ -183,3 +320,127 @@ fn filter_deps(x: &ObjectMember, name: &str) -> bool { _ => false, } } + +#[cfg(test)] +mod tests { + use super::*; + use presets::m2::requirejs_config::RequireJsClientConfig; + + #[test] + fn test_parse_all() { + let input = r#" + (function() { + var config = { + shim: { + "jquery/jquery-migrate": { + "deps": [ + "jquery" + ] + } + }, + config: { + mixins: { + "jquery/jstree/jquery.jstree": { + "mage/backend/jstree-mixin": true + } + } + }, + paths: { + 'trackingCode': 'Dotdigitalgroup_Email/js/trackingCode' + }, + map: { + '*': { + checkoutBalance: 'Magento_Customer/js/checkout-balance', + } + }, + deps: ["jquery"] + }; + require.config(config); + })(); + (function() { + var config = { + shim: { + paypalInContextExpressCheckout: { + exports: 'paypal', + deps: ['jquery'] + } + }, + config: { + mixins: { + "jquery/jstree/jquery.jstree": { + "mage/backend/jstree-mixin2": {}, + }, + "Magento_Checkout/js/action/place-order": { + "Magento_CheckoutAgreements/js/model/place-order-mixin": true + } + } + }, + paths: { + 'trackingCode': 'Dotdigitalgroup_Email/js/trackingCode-alt' + }, + map: { + '*': { + checkoutBalance: 'Magento_Customer/js/checkout-balance-alt', + checkoutBalance2: 'Magento_Customer/js/checkout-balance2', + }, + "other-map": { + someName: 'some/name' + } + } + }; + require.config(config); + })(); + "#; + + let o = ParsedConfig::from_str(input).expect("parses fixture"); + + let from = r#" + { + "config": { + "mixins": { + "Magento_Checkout/js/action/place-order": { + "Magento_CheckoutAgreements/js/model/place-order-mixin": true + }, + "jquery/jstree/jquery.jstree": { + "mage/backend/jstree-mixin": true, + "mage/backend/jstree-mixin2": {} + } + } + }, + "shim": { + "jquery/jquery-migrate": { + "deps": [ + "jquery" + ] + }, + "paypalInContextExpressCheckout": { + "exports": "paypal", + "deps": ["jquery"] + } + }, + "paths": { + "trackingCode": "Dotdigitalgroup_Email/js/trackingCode-alt" + }, + "map": { + "other-map": { + "someName": "some/name" + }, + "*": { + "checkoutBalance2": "Magento_Customer/js/checkout-balance2", + "checkoutBalance": "Magento_Customer/js/checkout-balance-alt" + } + }, + "deps": [ + "jquery" + ] + } + "#; + + let expected: serde_json::Value = + serde_json::from_str(&from).expect("serde from (fixture)"); + let actual = serde_json::to_value(&o).expect("Output serialized"); + assert_eq!(actual, expected); + let _as_require: RequireJsClientConfig = + serde_json::from_value(actual).expect("from value"); + } +} diff --git a/src/lib/presets/m2/requirejs_config.rs b/src/lib/presets/m2/requirejs_config.rs index 326b966..8b4cedf 100644 --- a/src/lib/presets/m2/requirejs_config.rs +++ b/src/lib/presets/m2/requirejs_config.rs @@ -1,9 +1,10 @@ use from_file::FromFile; use presets::m2::bundle_config::Module; use presets::m2::module_meta_data::ModuleData; +use presets::m2::parse::OutputError; +use presets::m2::parse::ParsedConfig; use serde_json; use std::collections::HashMap; -use url::Url; type ModuleId = String; @@ -18,6 +19,18 @@ pub struct RequireJsClientConfig { pub paths: HashMap, } +impl RequireJsClientConfig { + pub fn from_generated_string( + input: impl Into, + ) -> Result { + let output = ParsedConfig::from_str(input)?; + let as_serde = serde_json::to_value(&output).map_err(|_e| OutputError::Serialize)?; + let as_rjs: RequireJsClientConfig = + serde_json::from_value(as_serde).map_err(|_e| OutputError::Conversion)?; + Ok(as_rjs) + } +} + impl Default for RequireJsClientConfig { fn default() -> RequireJsClientConfig { RequireJsClientConfig { @@ -327,59 +340,24 @@ require.config({ ] } });"#; - // println!("{}", list); assert_eq!(list, expected); } -#[derive(Debug)] -pub struct BaseDirs { - pub dir: String, - pub base_url: String, -} - -pub fn base_to_dirs(input: &str) -> Result { - match Url::parse(input) { - Ok(mut url) => { - url.path_segments_mut() - .map_err(|_| "cannot be base") - .expect("url") - .pop_if_empty(); - let mut segs = url.path_segments().map(|c| c.collect::>()); - let mut last = segs - .clone() - .unwrap() - .pop() - .expect("can take last") - .to_string(); - let last_for_dir = last.clone(); - - let mut base_output = vec!["static"]; - let mut dir_output = vec!["static"]; - - for (_, item) in segs.expect("can iter over segs").iter().enumerate().skip(2) { - if *item != last.as_str() { - base_output.push(item); - dir_output.push(item); - } - } - - dir_output.push(&last_for_dir); - last.push_str("_src"); - base_output.push(&last); - - Ok(BaseDirs { - dir: dir_output.join("/"), - base_url: base_output.join("/"), - }) - } - Err(err) => Err(err.to_string()), - } -} - #[test] -fn test_base_to_dirs() { - let bd = base_to_dirs( - "https://127.0.0.1:8080/static/version1538053013/frontend/Graham/default/en_GB/", +fn test_parse_e2e() { + let input = include_str!("../../../../test/fixtures/requirejs-config-generated.js"); + let rjx = RequireJsClientConfig::from_generated_string(input).expect("allgood"); + assert_eq!( + rjx.deps, + vec![ + "jquery/jquery.mobile.custom", + "mage/common", + "mage/dataPost", + "mage/bootstrap", + "jquery/jquery-migrate", + "mage/translate-inline", + "Magento_Theme/js/responsive", + "Magento_Theme/js/theme", + ] ); - println!("{:?}", bd) } diff --git a/src/lib/presets/m2/static/post_config.js b/src/lib/presets/m2/static/post_config.js deleted file mode 100644 index dce7b7b..0000000 --- a/src/lib/presets/m2/static/post_config.js +++ /dev/null @@ -1,14 +0,0 @@ -; -var xhr = new XMLHttpRequest(); - -xhr.open('POST', '/__bs/post'); -xhr.setRequestHeader('Content-Type', 'application/json'); -xhr.onload = function() { - if (xhr.status === 200) { - console.log('config-gen: merged RequireJS config sent'); - } - else if (xhr.status !== 200) { - console.log('config-gen: request failed, returned status of ' + xhr.status); - } -}; -xhr.send(JSON.stringify(requirejs.s.contexts._.config)); diff --git a/test/fixtures/rjs-config-expected.json b/test/fixtures/rjs-config-expected.json new file mode 100644 index 0000000..d7596f4 --- /dev/null +++ b/test/fixtures/rjs-config-expected.json @@ -0,0 +1,234 @@ +{ + "waitSeconds": 0, + "baseUrl": "http://ce.demo.wearejh.com/static/version1517228438/frontend/Magento/luma/en_US/", + "paths": { + "jquery/ui": "jquery/jquery-ui", + "jquery/validate": "jquery/jquery.validate", + "jquery/hover-intent": "jquery/jquery.hoverIntent", + "jquery/file-uploader": "jquery/fileUploader/jquery.fileupload-fp", + "jquery/jquery.hashchange": "jquery/jquery.ba-hashchange.min", + "prototype": "legacy-build.min", + "jquery/jquery-storageapi": "jquery/jquery.storageapi.min", + "text": "mage/requirejs/text", + "domReady": "requirejs/domReady", + "tinymce": "tiny_mce/tiny_mce_src", + "ui/template": "Magento_Ui/templates", + "paypalInContextExpressCheckout": "https://www.paypalobjects.com/api/checkout", + "trackingCode": "Dotdigitalgroup_Email/js/trackingCode", + "temandoCheckoutFieldsDefinition": "Temando_Shipping/js/model/fields-definition", + "temandoCustomerAddressRateProcessor": "Temando_Shipping/js/model/shipping-rate-processor/customer-address", + "temandoNewAddressRateProcessor": "Temando_Shipping/js/model/shipping-rate-processor/new-address", + "temandoShippingRatesValidator": "Temando_Shipping/js/model/shipping-rates-validator/temando", + "temandoShippingRatesValidationRules": "Temando_Shipping/js/model/shipping-rates-validation-rules/temando" + }, + "bundles": {}, + "pkgs": {}, + "shim": { + "jquery/jquery-migrate": { + "deps": [ + "jquery" + ] + }, + "jquery/jquery.hashchange": { + "deps": [ + "jquery", + "jquery/jquery-migrate" + ] + }, + "jquery/jstree/jquery.hotkeys": { + "deps": [ + "jquery" + ] + }, + "jquery/hover-intent": { + "deps": [ + "jquery" + ] + }, + "mage/adminhtml/backup": { + "deps": [ + "prototype" + ] + }, + "mage/captcha": { + "deps": [ + "prototype" + ] + }, + "mage/common": { + "deps": [ + "jquery" + ] + }, + "mage/new-gallery": { + "deps": [ + "jquery" + ] + }, + "mage/webapi": { + "deps": [ + "jquery" + ] + }, + "jquery/ui": { + "deps": [ + "jquery" + ] + }, + "MutationObserver": { + "deps": [ + "es6-collections" + ] + }, + "tinymce": { + "exports": "tinymce" + }, + "moment": { + "exports": "moment" + }, + "matchMedia": { + "exports": "mediaCheck" + }, + "jquery/jquery-storageapi": { + "deps": [ + "jquery/jquery.cookie" + ] + }, + "vimeoAPI": {}, + "paypalInContextExpressCheckout": { + "exports": "paypal" + }, + "trackingCode": { + "exports": "_dmTrack" + } + }, + "config": { + "mixins": { + "jquery/jstree/jquery.jstree": { + "mage/backend/jstree-mixin": true + }, + "Magento_Checkout/js/action/place-order": { + "Magento_CheckoutAgreements/js/model/place-order-mixin": true + }, + "Magento_Checkout/js/action/set-payment-information": { + "Magento_CheckoutAgreements/js/model/set-payment-information-mixin": true + } + }, + "text": { + "headers": { + "X-Requested-With": "XMLHttpRequest" + } + } + }, + "map": { + "*": { + "rowBuilder": "Magento_Theme/js/row-builder", + "toggleAdvanced": "mage/toggle", + "translateInline": "mage/translate-inline", + "sticky": "mage/sticky", + "tabs": "mage/tabs", + "zoom": "mage/zoom", + "collapsible": "mage/collapsible", + "dropdownDialog": "mage/dropdown", + "dropdown": "mage/dropdowns", + "accordion": "mage/accordion", + "loader": "mage/loader", + "tooltip": "mage/tooltip", + "deletableItem": "mage/deletable-item", + "itemTable": "mage/item-table", + "fieldsetControls": "mage/fieldset-controls", + "fieldsetResetControl": "mage/fieldset-controls", + "redirectUrl": "mage/redirect-url", + "loaderAjax": "mage/loader", + "menu": "mage/menu", + "popupWindow": "mage/popup-window", + "validation": "mage/validation/validation", + "welcome": "Magento_Theme/js/view/welcome", + "ko": "knockoutjs/knockout", + "knockout": "knockoutjs/knockout", + "mageUtils": "mage/utils/main", + "rjsResolver": "mage/requirejs/resolver", + "checkoutBalance": "Magento_Customer/js/checkout-balance", + "address": "Magento_Customer/address", + "changeEmailPassword": "Magento_Customer/change-email-password", + "passwordStrengthIndicator": "Magento_Customer/js/password-strength-indicator", + "zxcvbn": "Magento_Customer/js/zxcvbn", + "addressValidation": "Magento_Customer/js/addressValidation", + "compareList": "Magento_Catalog/js/list", + "relatedProducts": "Magento_Catalog/js/related-products", + "upsellProducts": "Magento_Catalog/js/upsell-products", + "productListToolbarForm": "Magento_Catalog/js/product/list/toolbar", + "catalogGallery": "Magento_Catalog/js/gallery", + "priceBox": "Magento_Catalog/js/price-box", + "priceOptionDate": "Magento_Catalog/js/price-option-date", + "priceOptionFile": "Magento_Catalog/js/price-option-file", + "priceOptions": "Magento_Catalog/js/price-options", + "priceUtils": "Magento_Catalog/js/price-utils", + "catalogAddToCart": "Magento_Catalog/js/catalog-add-to-cart", + "addToCart": "Magento_Msrp/js/msrp", + "quickSearch": "Magento_Search/form-mini", + "bundleOption": "Magento_Bundle/bundle", + "priceBundle": "Magento_Bundle/js/price-bundle", + "slide": "Magento_Bundle/js/slide", + "productSummary": "Magento_Bundle/js/product-summary", + "creditCardType": "Magento_Payment/cc-type", + "downloadable": "Magento_Downloadable/downloadable", + "giftMessage": "Magento_Sales/gift-message", + "ordersReturns": "Magento_Sales/orders-returns", + "catalogSearch": "Magento_CatalogSearch/form-mini", + "requireCookie": "Magento_Cookie/js/require-cookie", + "cookieNotices": "Magento_Cookie/js/notices", + "discountCode": "Magento_Checkout/js/discount-codes", + "shoppingCart": "Magento_Checkout/js/shopping-cart", + "regionUpdater": "Magento_Checkout/js/region-updater", + "sidebar": "Magento_Checkout/js/sidebar", + "checkoutLoader": "Magento_Checkout/js/checkout-loader", + "checkoutData": "Magento_Checkout/js/checkout-data", + "proceedToCheckout": "Magento_Checkout/js/proceed-to-checkout", + "taxToggle": "Magento_Weee/tax-toggle", + "giftOptions": "Magento_GiftMessage/gift-options", + "extraOptions": "Magento_GiftMessage/extra-options", + "uiElement": "Magento_Ui/js/lib/core/element/element", + "uiCollection": "Magento_Ui/js/lib/core/collection", + "uiComponent": "Magento_Ui/js/lib/core/collection", + "uiClass": "Magento_Ui/js/lib/core/class", + "uiEvents": "Magento_Ui/js/lib/core/events", + "uiRegistry": "Magento_Ui/js/lib/registry/registry", + "consoleLogger": "Magento_Ui/js/lib/logger/console-logger", + "uiLayout": "Magento_Ui/js/core/renderer/layout", + "buttonAdapter": "Magento_Ui/js/form/button-adapter", + "configurable": "Magento_ConfigurableProduct/js/configurable", + "multiShipping": "Magento_Multishipping/js/multi-shipping", + "orderOverview": "Magento_Multishipping/js/overview", + "payment": "Magento_Multishipping/js/payment", + "recentlyViewedProducts": "Magento_Reports/js/recently-viewed", + "pageCache": "Magento_PageCache/js/page-cache", + "loadPlayer": "Magento_ProductVideo/js/load-player", + "fotoramaVideoEvents": "Magento_ProductVideo/js/fotorama-add-video-events", + "orderReview": "Magento_Paypal/order-review", + "paypalCheckout": "Magento_Paypal/js/paypal-checkout", + "transparent": "Magento_Payment/transparent", + "captcha": "Magento_Captcha/captcha", + "wishlist": "Magento_Wishlist/js/wishlist", + "addToWishlist": "Magento_Wishlist/js/add-to-wishlist", + "wishlistSearch": "Magento_Wishlist/js/search", + "editTrigger": "mage/edit-trigger", + "addClass": "Magento_Translation/add-class", + "braintree": "https://js.braintreegateway.com/js/braintree-2.32.0.min.js" + }, + "Magento_Checkout/js/model/shipping-rate-service": { + "Magento_Checkout/js/model/shipping-rate-processor/customer-address": "temandoCustomerAddressRateProcessor", + "Magento_Checkout/js/model/shipping-rate-processor/new-address": "temandoNewAddressRateProcessor" + } + }, + "deps": [ + "jquery/jquery.mobile.custom", + "mage/common", + "mage/dataPost", + "mage/bootstrap", + "jquery/jquery-migrate", + "mage/translate-inline", + "Magento_Theme/js/responsive", + "Magento_Theme/js/theme" + ] +} \ No newline at end of file diff --git a/test/fixtures/rjs-config.js b/test/fixtures/rjs-config.js new file mode 100644 index 0000000..29d8f28 --- /dev/null +++ b/test/fixtures/rjs-config.js @@ -0,0 +1,672 @@ +(function(require){ + (function() { + /** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ + + var config = { + map: { + '*': { + 'rowBuilder': 'Magento_Theme/js/row-builder', + 'toggleAdvanced': 'mage/toggle', + 'translateInline': 'mage/translate-inline', + 'sticky': 'mage/sticky', + 'tabs': 'mage/tabs', + 'zoom': 'mage/zoom', + 'collapsible': 'mage/collapsible', + 'dropdownDialog': 'mage/dropdown', + 'dropdown': 'mage/dropdowns', + 'accordion': 'mage/accordion', + 'loader': 'mage/loader', + 'tooltip': 'mage/tooltip', + 'deletableItem': 'mage/deletable-item', + 'itemTable': 'mage/item-table', + 'fieldsetControls': 'mage/fieldset-controls', + 'fieldsetResetControl': 'mage/fieldset-controls', + 'redirectUrl': 'mage/redirect-url', + 'loaderAjax': 'mage/loader', + 'menu': 'mage/menu', + 'popupWindow': 'mage/popup-window', + 'validation': 'mage/validation/validation', + 'welcome': 'Magento_Theme/js/view/welcome' + } + }, + paths: { + 'jquery/ui': 'jquery/jquery-ui' + }, + deps: [ + 'jquery/jquery.mobile.custom', + 'mage/common', + 'mage/dataPost', + 'mage/bootstrap' + ] + }; + + require.config(config); + })(); + (function() { + /** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ + + var config = { + 'waitSeconds': 0, + 'map': { + '*': { + 'ko': 'knockoutjs/knockout', + 'knockout': 'knockoutjs/knockout', + 'mageUtils': 'mage/utils/main', + 'rjsResolver': 'mage/requirejs/resolver' + } + }, + 'shim': { + 'jquery/jquery-migrate': ['jquery'], + 'jquery/jquery.hashchange': ['jquery', 'jquery/jquery-migrate'], + 'jquery/jstree/jquery.hotkeys': ['jquery'], + 'jquery/hover-intent': ['jquery'], + 'mage/adminhtml/backup': ['prototype'], + 'mage/captcha': ['prototype'], + 'mage/common': ['jquery'], + 'mage/new-gallery': ['jquery'], + 'mage/webapi': ['jquery'], + 'jquery/ui': ['jquery'], + 'MutationObserver': ['es6-collections'], + 'tinymce': { + 'exports': 'tinymce' + }, + 'moment': { + 'exports': 'moment' + }, + 'matchMedia': { + 'exports': 'mediaCheck' + }, + 'jquery/jquery-storageapi': { + 'deps': ['jquery/jquery.cookie'] + } + }, + 'paths': { + 'jquery/validate': 'jquery/jquery.validate', + 'jquery/hover-intent': 'jquery/jquery.hoverIntent', + 'jquery/file-uploader': 'jquery/fileUploader/jquery.fileupload-fp', + 'jquery/jquery.hashchange': 'jquery/jquery.ba-hashchange.min', + 'prototype': 'legacy-build.min', + 'jquery/jquery-storageapi': 'jquery/jquery.storageapi.min', + 'text': 'mage/requirejs/text', + 'domReady': 'requirejs/domReady', + 'tinymce': 'tiny_mce/tiny_mce_src' + }, + 'deps': [ + 'jquery/jquery-migrate' + ], + 'config': { + 'mixins': { + 'jquery/jstree/jquery.jstree': { + 'mage/backend/jstree-mixin': true + } + }, + 'text': { + 'headers': { + 'X-Requested-With': 'XMLHttpRequest' + } + } + } + }; + + require(['jquery'], function ($) { + 'use strict'; + + $.noConflict(); + }); + + require.config(config); + })(); + (function() { + /** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ + + var config = { + map: { + '*': { + checkoutBalance: 'Magento_Customer/js/checkout-balance', + address: 'Magento_Customer/address', + changeEmailPassword: 'Magento_Customer/change-email-password', + passwordStrengthIndicator: 'Magento_Customer/js/password-strength-indicator', + zxcvbn: 'Magento_Customer/js/zxcvbn', + addressValidation: 'Magento_Customer/js/addressValidation' + } + } + }; + + require.config(config); + })(); + (function() { + /** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ + + var config = { + map: { + '*': { + compareList: 'Magento_Catalog/js/list', + relatedProducts: 'Magento_Catalog/js/related-products', + upsellProducts: 'Magento_Catalog/js/upsell-products', + productListToolbarForm: 'Magento_Catalog/js/product/list/toolbar', + catalogGallery: 'Magento_Catalog/js/gallery', + priceBox: 'Magento_Catalog/js/price-box', + priceOptionDate: 'Magento_Catalog/js/price-option-date', + priceOptionFile: 'Magento_Catalog/js/price-option-file', + priceOptions: 'Magento_Catalog/js/price-options', + priceUtils: 'Magento_Catalog/js/price-utils', + catalogAddToCart: 'Magento_Catalog/js/catalog-add-to-cart' + } + } + }; + + require.config(config); + })(); + (function() { + /** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ + + var config = { + map: { + '*': { + addToCart: 'Magento_Msrp/js/msrp' + } + } + }; + + require.config(config); + })(); + (function() { + /** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ + + var config = { + map: { + '*': { + quickSearch: 'Magento_Search/form-mini' + } + } + }; + + require.config(config); + })(); + (function() { + /** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ + + var config = { + map: { + '*': { + bundleOption: 'Magento_Bundle/bundle', + priceBundle: 'Magento_Bundle/js/price-bundle', + slide: 'Magento_Bundle/js/slide', + productSummary: 'Magento_Bundle/js/product-summary' + } + } + }; + + require.config(config); + })(); + (function() { + /** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ + + var config = { + map: { + '*': { + creditCardType: 'Magento_Payment/cc-type' + } + } + }; + + require.config(config); + })(); + (function() { + /** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ + + var config = { + map: { + '*': { + downloadable: 'Magento_Downloadable/downloadable' + } + } + }; + + require.config(config); + })(); + (function() { + /** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ + + var config = { + map: { + '*': { + giftMessage: 'Magento_Sales/gift-message', + ordersReturns: 'Magento_Sales/orders-returns' + } + } + }; + + require.config(config); + })(); + (function() { + /** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ + + var config = { + map: { + '*': { + catalogSearch: 'Magento_CatalogSearch/form-mini' + } + } + }; + + require.config(config); + })(); + (function() { + /** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ + + var config = { + map: { + '*': { + requireCookie: 'Magento_Cookie/js/require-cookie', + cookieNotices: 'Magento_Cookie/js/notices' + } + } + }; + + require.config(config); + })(); + (function() { + /** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ + + var config = { + map: { + '*': { + discountCode: 'Magento_Checkout/js/discount-codes', + shoppingCart: 'Magento_Checkout/js/shopping-cart', + regionUpdater: 'Magento_Checkout/js/region-updater', + sidebar: 'Magento_Checkout/js/sidebar', + checkoutLoader: 'Magento_Checkout/js/checkout-loader', + checkoutData: 'Magento_Checkout/js/checkout-data', + proceedToCheckout: 'Magento_Checkout/js/proceed-to-checkout' + } + } + }; + + require.config(config); + })(); + (function() { + /** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ + + var config = { + map: { + '*': { + 'taxToggle': 'Magento_Weee/tax-toggle' + } + } + }; + + require.config(config); + })(); + (function() { + /** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ + + var config = { + map: { + '*': { + giftOptions: 'Magento_GiftMessage/gift-options', + extraOptions: 'Magento_GiftMessage/extra-options' + } + } + }; + + require.config(config); + })(); + (function() { + /** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ + + var config = { + paths: { + 'ui/template': 'Magento_Ui/templates' + }, + map: { + '*': { + uiElement: 'Magento_Ui/js/lib/core/element/element', + uiCollection: 'Magento_Ui/js/lib/core/collection', + uiComponent: 'Magento_Ui/js/lib/core/collection', + uiClass: 'Magento_Ui/js/lib/core/class', + uiEvents: 'Magento_Ui/js/lib/core/events', + uiRegistry: 'Magento_Ui/js/lib/registry/registry', + consoleLogger: 'Magento_Ui/js/lib/logger/console-logger', + uiLayout: 'Magento_Ui/js/core/renderer/layout', + buttonAdapter: 'Magento_Ui/js/form/button-adapter' + } + } + }; + + require.config(config); + })(); + (function() { + /** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ + + var config = { + map: { + '*': { + configurable: 'Magento_ConfigurableProduct/js/configurable' + } + } + }; + + require.config(config); + })(); + (function() { + /** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ + + var config = { + map: { + '*': { + multiShipping: 'Magento_Multishipping/js/multi-shipping', + orderOverview: 'Magento_Multishipping/js/overview', + payment: 'Magento_Multishipping/js/payment' + } + } + }; + + require.config(config); + })(); + (function() { + /** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ + + var config = { + map: { + '*': { + recentlyViewedProducts: 'Magento_Reports/js/recently-viewed' + } + } + }; + + require.config(config); + })(); + (function() { + /** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ + + var config = { + map: { + '*': { + pageCache: 'Magento_PageCache/js/page-cache' + } + } + }; + + require.config(config); + })(); + (function() { + /** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ + + var config = { + map: { + '*': { + loadPlayer: 'Magento_ProductVideo/js/load-player', + fotoramaVideoEvents: 'Magento_ProductVideo/js/fotorama-add-video-events' + } + }, + shim: { + vimeoAPI: {} + } + }; + + require.config(config); + })(); + (function() { + /** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ + + var config = { + map: { + '*': { + orderReview: 'Magento_Paypal/order-review', + paypalCheckout: 'Magento_Paypal/js/paypal-checkout' + } + }, + paths: { + paypalInContextExpressCheckout: 'https://www.paypalobjects.com/api/checkout' + }, + shim: { + paypalInContextExpressCheckout: { + exports: 'paypal' + } + } + }; + + require.config(config); + })(); + (function() { + /** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ + + var config = { + map: { + '*': { + transparent: 'Magento_Payment/transparent' + } + } + }; + + require.config(config); + })(); + (function() { + /** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ + + var config = { + config: { + mixins: { + 'Magento_Checkout/js/action/place-order': { + 'Magento_CheckoutAgreements/js/model/place-order-mixin': true + }, + 'Magento_Checkout/js/action/set-payment-information': { + 'Magento_CheckoutAgreements/js/model/set-payment-information-mixin': true + } + } + } + }; + + require.config(config); + })(); + (function() { + /** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ + + var config = { + map: { + '*': { + captcha: 'Magento_Captcha/captcha' + } + } + }; + + require.config(config); + })(); + (function() { + /** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ + + var config = { + map: { + '*': { + wishlist: 'Magento_Wishlist/js/wishlist', + addToWishlist: 'Magento_Wishlist/js/add-to-wishlist', + wishlistSearch: 'Magento_Wishlist/js/search' + } + } + }; + + require.config(config); + })(); + (function() { + /** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ + + var config = { + map: { + '*': { + transparent: 'Magento_Payment/transparent' + } + } + }; + + require.config(config); + })(); + (function() { + /** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ + + var config = { + map: { + '*': { + editTrigger: 'mage/edit-trigger', + addClass: 'Magento_Translation/add-class' + } + }, + deps: [ + 'mage/translate-inline' + ] + }; + + require.config(config); + })(); + (function() { + /** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ + + var config = { + map: { + '*': { + braintree: 'https://js.braintreegateway.com/js/braintree-2.32.0.min.js' + } + } + }; + + require.config(config); + })(); + (function() { + var config = { + 'paths': { + 'trackingCode': 'Dotdigitalgroup_Email/js/trackingCode' + }, + 'shim': { + 'trackingCode': { + exports: '_dmTrack' + } + } + }; + + require.config(config); + })(); + (function() { + var config = { + paths: { + temandoCheckoutFieldsDefinition: 'Temando_Shipping/js/model/fields-definition', + temandoCustomerAddressRateProcessor: 'Temando_Shipping/js/model/shipping-rate-processor/customer-address', + temandoNewAddressRateProcessor: 'Temando_Shipping/js/model/shipping-rate-processor/new-address', + temandoShippingRatesValidator: 'Temando_Shipping/js/model/shipping-rates-validator/temando', + temandoShippingRatesValidationRules: 'Temando_Shipping/js/model/shipping-rates-validation-rules/temando' + }, + map: { + 'Magento_Checkout/js/model/shipping-rate-service': { + 'Magento_Checkout/js/model/shipping-rate-processor/customer-address' : 'temandoCustomerAddressRateProcessor', + 'Magento_Checkout/js/model/shipping-rate-processor/new-address' : 'temandoNewAddressRateProcessor' + } + } + }; + + require.config(config); + })(); + (function() { + /** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ + + var config = { + deps: [ + 'Magento_Theme/js/responsive', + 'Magento_Theme/js/theme' + ] + }; + + require.config(config); + })(); + + + +})(require); \ No newline at end of file