From b2de52888a7c976cc9ae40518e3653cec0aac296 Mon Sep 17 00:00:00 2001 From: Jose Antonio Marquez Date: Sun, 4 Mar 2012 11:15:27 -0800 Subject: Improved CSS URL cleaned Added logic to accommodate any URLs in a CSS file inside the opened document root. Need to add logic for handling linked references above the root. Also need to reformat into a reusable method as it might be needed besides CSS. --- js/mediators/io-mediator.js | 66 ++++++++++++++++++++++++++++++++++----------- 1 file changed, 51 insertions(+), 15 deletions(-) diff --git a/js/mediators/io-mediator.js b/js/mediators/io-mediator.js index 0a851a4d..5917edba 100644 --- a/js/mediators/io-mediator.js +++ b/js/mediators/io-mediator.js @@ -330,29 +330,65 @@ exports.IoMediator = Montage.create(Component, { } } } - var local, regex, fileCouldDirUrl, adjCss = this.getCssFromRules(template.css[i].cssRules), cssUrl = template.css[i].ownerNode.getAttribute('data-ninja-file-url'); - //TODO: Assure logic for local directory - local = cssUrl.split(cssUrl.split('/')[cssUrl.split('/').length-2])[0] || cssUrl.split(cssUrl.split('/')[cssUrl.split('/').length-1])[0] || cssUrl.split(cssUrl.split('/')[0])[0]; - // - fileCouldDirUrl = this.application.ninja.coreIoApi.rootUrl+escape((this.application.ninja.documentController.documentHackReference.root.split(this.application.ninja.coreIoApi.cloudData.root)[1]+local).replace(/\/\//gi, '/')); - // - regex = new RegExp(fileCouldDirUrl.replace(/\//gi, '\\\/'), 'gi'); - // - if (local.split('/').length > 2) { - adjCss = adjCss.replace(regex, '../'); - } else { - adjCss = adjCss.replace(regex, ''); + + /////////////////////////////////////////////////////////////////////////////////////////// + /////////////////////////////////////////////////////////////////////////////////////////// + + + var cleanedCss, fileCouldDirUrl, pathDepth, pathToDocRoot = '../'; + dirtyCss = this.getCssFromRules(template.css[i].cssRules), + fileUrl = template.css[i].ownerNode.getAttribute('data-ninja-file-url'), + fileRootUrl = this.application.ninja.coreIoApi.rootUrl+escape((this.application.ninja.documentController.documentHackReference.root.split(this.application.ninja.coreIoApi.cloudData.root)[1]+fileUrl.split(fileUrl.split('/')[fileUrl.split('/').length-1])[0]).replace(/\/\//gi, '/')), + localPath = fileUrl.split(fileUrl.split('/')[fileUrl.split('/').length-2])[0] || fileUrl.split(fileUrl.split('/')[fileUrl.split('/').length-1])[0] || fileUrl.split(fileUrl.split('/')[0])[0], + documentRootURL = this.application.ninja.coreIoApi.rootUrl+escape((this.application.ninja.documentController.documentHackReference.root.split(this.application.ninja.coreIoApi.cloudData.root)[1])); + + pathDepth = Math.floor(localPath.split('/').length/2); + + for (var p=0; p < pathDepth; p++) { + pathToDocRoot += '../'; + } + + fileCouldDirUrl = this.application.ninja.coreIoApi.rootUrl+escape((this.application.ninja.documentController.documentHackReference.root.split(this.application.ninja.coreIoApi.cloudData.root)[1]+localPath).replace(/\/\//gi, '/')); + + cleanedCss = dirtyCss.replace(/(\b(?:(?:https?|ftp|file|[A-Za-z]+):\/\/|www\.|ftp\.)(?:\([-A-Z0-9+&@#\/%=~_|$?!:,.]*\)|[-A-Z0-9+&@#\/%=~_|$?!:,.])*(?:\([-A-Z0-9+&@#\/%=~_|$?!:,.]*\)|[A-Z0-9+&@#\/%=~_|$]))/gi, parseNinjaUrl.bind(this)); + + function parseNinjaUrl (url) { + // + if (url.indexOf(fileCouldDirUrl) !== -1 || url.indexOf(fileRootUrl) !== -1) { + // + if (pathDepth < 1 || url.indexOf(fileRootUrl) > -1) { + // + url = url.replace(new RegExp(fileRootUrl.replace(/\//gi, '\\\/'), 'gi'), ''); + } else { + // + url = url.replace(new RegExp(fileCouldDirUrl.replace(/\//gi, '\\\/'), 'gi'), '../'); + } + } else { + // + if (url.indexOf(documentRootURL) !== 1) { + url = url.replace(new RegExp(documentRootURL.replace(/\//gi, '\\\/'), 'gi'), pathToDocRoot); + } else if (url.indexOf(this.application.ninja.coreIoApi.rootUrl) !== 1) { + //TODO: Add logic for files above root document folder + } + } + //console.log("Returning: " + url); + //console.log("-----"); + return url; } + //console.log(cleanedCss); + + /////////////////////////////////////////////////////////////////////////////////////////// + /////////////////////////////////////////////////////////////////////////////////////////// + - //console.log(adjCss); - //console.log(fileCouldDirUrl); //return; //Saving data from rules array converted to string into file - var save = this.fio.saveFile({uri: template.css[i].ownerNode.getAttribute('data-ninja-uri'), contents: adjCss}); + var save = this.fio.saveFile({uri: template.css[i].ownerNode.getAttribute('data-ninja-uri'), contents: cleanedCss}); + //TODO: Add error handling for saving files } } } -- cgit v1.2.3 From 195624da6d0c5d15bcde8a8655355544687ef58a Mon Sep 17 00:00:00 2001 From: Jose Antonio Marquez Date: Sun, 4 Mar 2012 19:21:34 -0800 Subject: Setting up document level URL parsing Set up logic to parse URLs document level (href, src, url) still need to add functionality to return proper value, currently only detecting current value. --- js/document/html-document.js | 22 +++++++++++++--------- 1 file changed, 13 insertions(+), 9 deletions(-) diff --git a/js/document/html-document.js b/js/document/html-document.js index a56a7e3c..1e41a797 100755 --- a/js/document/html-document.js +++ b/js/document/html-document.js @@ -408,10 +408,18 @@ exports.HTMLDocument = Montage.create(TextDocument, { // if(!this.documentRoot.Ninja) this.documentRoot.Ninja = {}; //Inserting user's document into template - this._templateDocument.head.innerHTML = this._userDocument.content.head; - this._templateDocument.body.innerHTML = this._userDocument.content.body; - //TODO: Use querySelectorAll - var scripttags = this._templateDocument.html.getElementsByTagName('script'), webgldata; + + //TODO: Add logic to parse URLs from head/body + this._templateDocument.head.innerHTML = (this._userDocument.content.head.replace(/\b(href|src)\s*=\s*"([^"]*)"/g, ninjaUrlRedirect.bind(this))).replace(/url\(([^"]*)(.+?)\1\)/g, ninjaUrlRedirect.bind(this)); + this._templateDocument.body.innerHTML = (this._userDocument.content.body.replace(/\b(href|src)\s*=\s*"([^"]*)"/g, ninjaUrlRedirect.bind(this))).replace(/url\(([^"]*)(.+?)\1\)/g, ninjaUrlRedirect.bind(this)); + // + function ninjaUrlRedirect (prop) { + console.log(prop); + return prop; + } + // + + var scripttags = this._templateDocument.html.getElementsByTagName('script'), webgldata; //TODO: Use querySelectorAll // for (var w in scripttags) { if (scripttags[w].getAttribute) { @@ -513,13 +521,9 @@ exports.HTMLDocument = Montage.create(TextDocument, { //TODO: Fix regEx to have logic for all possible URLs strings (currently prefixing all url()) - prefixUrl = 'url('+fileCouldDirUrl; + prefixUrl = 'url('+fileCouldDirUrl; //This should be re-written with better RegEx tag.innerHTML = cssData.content.replace(/url\(/gi, prefixUrl); - //console.log(("http://hello.com, https://google.com").replace(/(\b(?:(?:https?|ftp|file|[A-Za-z]+):\/\/|www\.|ftp\.)(?:\([-A-Z0-9+&@#\/%=~_|$?!:,.]*\)|[-A-Z0-9+&@#\/%=~_|$?!:,.])*(?:\([-A-Z0-9+&@#\/%=~_|$?!:,.]*\)|[A-Z0-9+&@#\/%=~_|$]))/gi, 'hello')) - - //console.log(tag.innerHTML); - //Looping through DOM to insert style tag at location of link element query = this._templateDocument.html.querySelectorAll(['link']); for (var j in query) { -- cgit v1.2.3 From 56efed8b1ed9974aade615fce2d96bc214d21540 Mon Sep 17 00:00:00 2001 From: Jose Antonio Marquez Date: Mon, 5 Mar 2012 15:55:30 -0800 Subject: Resolved URL path issues in document and CSS Added logic to allow for files opened and assets linked in any order all under the cloud server root. --- js/document/html-document.js | 121 ++++++++++++++++++++++++++++++++++++++++--- js/mediators/io-mediator.js | 63 +++++++++++----------- 2 files changed, 143 insertions(+), 41 deletions(-) diff --git a/js/document/html-document.js b/js/document/html-document.js index 1e41a797..ace1390f 100755 --- a/js/document/html-document.js +++ b/js/document/html-document.js @@ -409,16 +409,57 @@ exports.HTMLDocument = Montage.create(TextDocument, { if(!this.documentRoot.Ninja) this.documentRoot.Ninja = {}; //Inserting user's document into template - //TODO: Add logic to parse URLs from head/body + + + + + + + + + //////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + + //TODO: Clean up and make public method to prepend properties with Ninja URL this._templateDocument.head.innerHTML = (this._userDocument.content.head.replace(/\b(href|src)\s*=\s*"([^"]*)"/g, ninjaUrlRedirect.bind(this))).replace(/url\(([^"]*)(.+?)\1\)/g, ninjaUrlRedirect.bind(this)); this._templateDocument.body.innerHTML = (this._userDocument.content.body.replace(/\b(href|src)\s*=\s*"([^"]*)"/g, ninjaUrlRedirect.bind(this))).replace(/url\(([^"]*)(.+?)\1\)/g, ninjaUrlRedirect.bind(this)); // + //var docRootUrl = this.application.ninja.coreIoApi.rootUrl+escape((this.application.ninja.documentController.documentHackReference.root.split(this.application.ninja.coreIoApi.cloudData.root)[1]).replace(/\/\//gi, '/')); + // function ninjaUrlRedirect (prop) { - console.log(prop); + //Checking for property value to not contain a full direct URL + if (!prop.match(/(\b(?:(?:https?|ftp|file|[A-Za-z]+):\/\/|www\.|ftp\.)(?:\([-A-Z0-9+&@#\/%=~_|$?!:,.]*\)|[-A-Z0-9+&@#\/%=~_|$?!:,.])*(?:\([-A-Z0-9+&@#\/%=~_|$?!:,.]*\)|[A-Z0-9+&@#\/%=~_|$]))/gi)) { + //Checking for attributes and type of source + if (prop.indexOf('href') !== -1 || prop.indexOf('src') !== -1) { //From HTML attribute + // + prop = prop.replace(/"([^"]*)"/gi, ninjaUrlPrepend.bind(this)); + } else if (prop.indexOf('url') !== -1) { //From CSS property + //TODO: Add functionality + console.log('CSS: '+prop); + } + } return prop; } // - + function ninjaUrlPrepend (url) { + var docRootUrl = this.application.ninja.coreIoApi.rootUrl+escape((this.application.ninja.documentController.documentHackReference.root.split(this.application.ninja.coreIoApi.cloudData.root)[1]).replace(/\/\//gi, '/')); + return '"'+docRootUrl+url.replace(/\"/gi, '')+'"'; + } + + //////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + + + + + + + + + + var scripttags = this._templateDocument.html.getElementsByTagName('script'), webgldata; //TODO: Use querySelectorAll // for (var w in scripttags) { @@ -493,10 +534,55 @@ exports.HTMLDocument = Montage.create(TextDocument, { //If rules are null, assuming cross-origin issue if(this._document.styleSheets[i].rules === null) { //TODO: Revisit URLs and URI creation logic, very hack right now - var fileUri, cssUrl, cssData, query, prefixUrl, fileCouldDirUrl; + var fileUri, cssUrl, cssData, query, prefixUrl, fileCouldDirUrl, docRootUrl; + // + docRootUrl = this.application.ninja.coreIoApi.rootUrl+escape((this.application.ninja.documentController.documentHackReference.root.split(this.application.ninja.coreIoApi.cloudData.root)[1]).replace(/\/\//gi, '/')); //TODO: Parse out relative URLs and map them to absolute - if (this._document.styleSheets[i].href.indexOf(chrome.extension.getURL('')) !== -1) { - //Getting the url of the CSS file + if (this._document.styleSheets[i].href.indexOf(this.application.ninja.coreIoApi.rootUrl) !== -1) { + + cssUrl = this._document.styleSheets[i].href.split(this.application.ninja.coreIoApi.rootUrl)[1]; + fileUri = this.application.ninja.coreIoApi.cloudData.root+cssUrl; + //TODO: Add error handling for reading file + cssData = this.application.ninja.coreIoApi.readFile({uri: fileUri}); + + + var tag = this.iframe.contentWindow.document.createElement('style'); + tag.setAttribute('type', 'text/css'); + tag.setAttribute('data-ninja-uri', fileUri); + tag.setAttribute('data-ninja-file-url', cssUrl); + tag.setAttribute('data-ninja-file-read-only', JSON.parse(this.application.ninja.coreIoApi.isFileWritable({uri: fileUri}).content).readOnly); + tag.setAttribute('data-ninja-file-name', cssUrl.split('/')[cssUrl.split('/').length-1]); + //Copying attributes to maintain same properties as the + for (var n in this._document.styleSheets[i].ownerNode.attributes) { + if (this._document.styleSheets[i].ownerNode.attributes[n].value && this._document.styleSheets[i].ownerNode.attributes[n].name !== 'disabled' && this._document.styleSheets[i].ownerNode.attributes[n].name !== 'disabled') { + if (this._document.styleSheets[i].ownerNode.attributes[n].value.indexOf(docRootUrl) !== -1) { + tag.setAttribute(this._document.styleSheets[i].ownerNode.attributes[n].name, this._document.styleSheets[i].ownerNode.attributes[n].value.split(docRootUrl)[1]); + } else { + tag.setAttribute(this._document.styleSheets[i].ownerNode.attributes[n].name, this._document.styleSheets[i].ownerNode.attributes[n].value); + } + } + } + + fileCouldDirUrl = this._document.styleSheets[i].href.split(this._document.styleSheets[i].href.split('/')[this._document.styleSheets[i].href.split('/').length-1])[0]; + prefixUrl = 'url('+fileCouldDirUrl; //This should be re-written with better RegEx + tag.innerHTML = cssData.content.replace(/url\(/gi, prefixUrl); + + + + //Looping through DOM to insert style tag at location of link element + query = this._templateDocument.html.querySelectorAll(['link']); + for (var j in query) { + if (query[j].href === this._document.styleSheets[i].href) { + //Disabling style sheet to reload via inserting in style tag + query[j].setAttribute('disabled', 'true'); + //Inserting tag + this._templateDocument.head.insertBefore(tag, query[j]); + } + } + + + /* +//Getting the url of the CSS file cssUrl = this._document.styleSheets[i].href.split('js/document/templates/montage-html')[1];//TODO: Parse out relative URLs and map them to absolute //Creating the URI of the file (this is wrong should not be splitting cssUrl) fileUri = (this.application.ninja.coreIoApi.cloudData.root+this.application.ninja.documentController.documentHackReference.root.split(this.application.ninja.coreIoApi.cloudData.root)[1]+cssUrl).replace(/\/\//gi, '/'); @@ -517,8 +603,8 @@ exports.HTMLDocument = Montage.create(TextDocument, { } // - fileCouldDirUrl = this.application.ninja.coreIoApi.rootUrl+escape((this.application.ninja.documentController.documentHackReference.root.split(this.application.ninja.coreIoApi.cloudData.root)[1]+cssUrl.split(cssUrl.split('/')[cssUrl.split('/').length-1])[0]).replace(/\/\//gi, '/')); - + //fileCouldDirUrl = this.application.ninja.coreIoApi.rootUrl+escape((this.application.ninja.documentController.documentHackReference.root.split(this.application.ninja.coreIoApi.cloudData.root)[1]+cssUrl.split(cssUrl.split('/')[cssUrl.split('/').length-1])[0]).replace(/\/\//gi, '/')); + fileCouldDirUrl = this.application.ninja.coreIoApi.rootUrl+escape((this.application.ninja.documentController.documentHackReference.root.split(this.application.ninja.coreIoApi.cloudData.root)[1]).replace(/\/\//gi, '/')); //TODO: Fix regEx to have logic for all possible URLs strings (currently prefixing all url()) prefixUrl = 'url('+fileCouldDirUrl; //This should be re-written with better RegEx @@ -534,6 +620,25 @@ exports.HTMLDocument = Montage.create(TextDocument, { this._templateDocument.head.insertBefore(tag, query[j]); } } +*/ + + + + + + + + + + + + + + + + + + } else { console.log('ERROR: Cross-Domain-Stylesheet detected, unable to load in Ninja'); //None local stylesheet, probably on a CDN (locked) diff --git a/js/mediators/io-mediator.js b/js/mediators/io-mediator.js index 5917edba..c02710c2 100644 --- a/js/mediators/io-mediator.js +++ b/js/mediators/io-mediator.js @@ -213,9 +213,11 @@ exports.IoMediator = Montage.create(Component, { parseNinjaTemplateToHtml: { enumerable: false, value: function (template) { + var regexRootUrl, rootUrl = this.application.ninja.coreIoApi.rootUrl+escape((this.application.ninja.documentController.documentHackReference.root.split(this.application.ninja.coreIoApi.cloudData.root)[1])); + regexRootUrl = new RegExp(rootUrl.replace(/\//gi, '\\\/'), 'gi'); //Injecting head and body into old document - template.document.content.document.head.innerHTML = template.head; - template.document.content.document.body.innerHTML = template.body; + template.document.content.document.head.innerHTML = template.head.replace(regexRootUrl, ''); + template.document.content.document.body.innerHTML = template.body.replace(regexRootUrl, ''); //Getting all CSS (style or link) tags var styletags = template.document.content.document.getElementsByTagName('style'), linktags = template.document.content.document.getElementsByTagName('link'), @@ -248,7 +250,7 @@ exports.IoMediator = Montage.create(Component, { for (var l in linktags) { if (linktags[l].getAttribute && linktags[l].getAttribute('disabled')) {//TODO: Use querySelectorAll for (var p=0; toremovetags[p]; p++) { - if (toremovetags[p].getAttribute('data-ninja-file-url') === ('/'+linktags[l].getAttribute('href'))) { + if (toremovetags[p].getAttribute('href') === linktags[l].getAttribute('href')) { if (!toremovetags[p].getAttribute('data-ninja-disabled')) { linktags[l].removeAttribute('disabled'); } @@ -335,55 +337,50 @@ exports.IoMediator = Montage.create(Component, { /////////////////////////////////////////////////////////////////////////////////////////// - var cleanedCss, fileCouldDirUrl, pathDepth, pathToDocRoot = '../'; + var cleanedCss, dirtyCss = this.getCssFromRules(template.css[i].cssRules), fileUrl = template.css[i].ownerNode.getAttribute('data-ninja-file-url'), - fileRootUrl = this.application.ninja.coreIoApi.rootUrl+escape((this.application.ninja.documentController.documentHackReference.root.split(this.application.ninja.coreIoApi.cloudData.root)[1]+fileUrl.split(fileUrl.split('/')[fileUrl.split('/').length-1])[0]).replace(/\/\//gi, '/')), - localPath = fileUrl.split(fileUrl.split('/')[fileUrl.split('/').length-2])[0] || fileUrl.split(fileUrl.split('/')[fileUrl.split('/').length-1])[0] || fileUrl.split(fileUrl.split('/')[0])[0], - documentRootURL = this.application.ninja.coreIoApi.rootUrl+escape((this.application.ninja.documentController.documentHackReference.root.split(this.application.ninja.coreIoApi.cloudData.root)[1])); - - pathDepth = Math.floor(localPath.split('/').length/2); - - for (var p=0; p < pathDepth; p++) { - pathToDocRoot += '../'; - } - - fileCouldDirUrl = this.application.ninja.coreIoApi.rootUrl+escape((this.application.ninja.documentController.documentHackReference.root.split(this.application.ninja.coreIoApi.cloudData.root)[1]+localPath).replace(/\/\//gi, '/')); - - cleanedCss = dirtyCss.replace(/(\b(?:(?:https?|ftp|file|[A-Za-z]+):\/\/|www\.|ftp\.)(?:\([-A-Z0-9+&@#\/%=~_|$?!:,.]*\)|[-A-Z0-9+&@#\/%=~_|$?!:,.])*(?:\([-A-Z0-9+&@#\/%=~_|$?!:,.]*\)|[A-Z0-9+&@#\/%=~_|$]))/gi, parseNinjaUrl.bind(this)); + fileRootUrl = this.application.ninja.coreIoApi.rootUrl+fileUrl.split(fileUrl.split('/')[fileUrl.split('/').length-1])[0], + cleanedCss = dirtyCss.replace(/(\b(?:(?:https?|ftp|file|[A-Za-z]+):\/\/|www\.|ftp\.)(?:\([-A-Z0-9+&@#\/%=~_|$?!:,.]*\)|[-A-Z0-9+&@#\/%=~_|$?!:,.])*(?:\([-A-Z0-9+&@#\/%=~_|$?!:,.]*\)|[A-Z0-9+&@#\/%=~_|$]))/gi, parseNinjaUrl.bind(this)); + function parseNinjaUrl (url) { + //console.log("Getting: " + url); // - if (url.indexOf(fileCouldDirUrl) !== -1 || url.indexOf(fileRootUrl) !== -1) { + if (url.indexOf(fileRootUrl) !== -1) { + url = url.replace(new RegExp(fileRootUrl.replace(/\//gi, '\\\/'), 'gi'), ''); + } else { + var assetsDirs = (url.replace(new RegExp((this.application.ninja.coreIoApi.rootUrl).replace(/\//gi, '\\\/'), 'gi'), '')).split('/'); + var fileDirs = (fileUrl.split(fileUrl.split('/')[fileUrl.split('/').length-1])[0]).split('/'); + var counter = 0; + var path = ''; + var newURL = ''; + // + for (var p=0; p < fileDirs.length-1; p++) { + if (fileDirs[p] === assetsDirs[p]) { + counter++; + } + } // - if (pathDepth < 1 || url.indexOf(fileRootUrl) > -1) { - // - url = url.replace(new RegExp(fileRootUrl.replace(/\//gi, '\\\/'), 'gi'), ''); - } else { - // - url = url.replace(new RegExp(fileCouldDirUrl.replace(/\//gi, '\\\/'), 'gi'), '../'); + for (var p=0; p < (fileDirs.length-counter)-1; p++) { + path += '../'; } - } else { // - if (url.indexOf(documentRootURL) !== 1) { - url = url.replace(new RegExp(documentRootURL.replace(/\//gi, '\\\/'), 'gi'), pathToDocRoot); - } else if (url.indexOf(this.application.ninja.coreIoApi.rootUrl) !== 1) { - //TODO: Add logic for files above root document folder + for (var p=counter; p < assetsDirs.length; p++) { + newURL += '/'+assetsDirs[p]; } + // + url = (path+newURL).replace(/\/\//gi, '/'); } //console.log("Returning: " + url); //console.log("-----"); return url; } - //console.log(cleanedCss); - /////////////////////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////////////////// - //return; - //Saving data from rules array converted to string into file -- cgit v1.2.3