2012-01-29 27 views
15

Estoy construyendo una extensión de Chrome que agrega algo de JavaScript a los artículos de Wikipedia. Por lo que yo sé, la única manera de utilizar RequireJS es añadir la líneaRequireJS en una extensión de Chrome

<script data-main="scripts/bla" src="scripts/require-jquery.js> 

Sin embargo, en mi extensión de Chrome, no tengo acceso al código HTML para agregar esta línea. ¿Alguna sugerencia?

+0

Podría aclarar esto un poco más? La forma en que normalmente incluiría módulos con require.js sería a través de javascript, no una etiqueta de script: require (["some/module", "a.js", "b.js"]); – Julian

+0

Sé cómo incluir módulos, pero ¿cómo incluyo requireJS * en sí mismo * después de cargar la página, y solo uso JavaScript? – Randomblue

+0

Esta no es una respuesta real a su pregunta, pero puede usar simplemente crear un script de greasemonkey y ejecutar todo su código de JavaScript [http://greasemonkey.mozdev.org/authoring.html](http://greasemonkey.mozdev .org/authoring.html) – tyranitar

Respuesta

17

Tiene acceso al DOM de la página desde la Extensión de Chrome a través de content script, sin embargo, la secuencia de comandos de contenido solo tendrá acceso a los objetos JavaScript creados por el content script.

Hay muchas formas de incluir scripts desde una extensión de Chrome; la forma en que la incluya se basará en lo que planea hacer con ella.

Si desea que en la página emergente de un browser o page action Puede incluir desde el manifiesto como un guión de contenido o hacer referencia a él mediante una etiqueta de script en el popup.html de un recurso relativo en su plugin.

Desde manifiesta:

{ 
    "name": "My extension", 
    ... 
    "content_scripts": [ 
    { 
     "matches": ["http://www.google.com/*"], 
     "css": ["mystyles.css"], 
     "js": ["jquery.js", "myscript.js"] 
    } 
    ], 
    ... 
} 

De popup.html:

<script data-main="scripts/bla" src="scripts/require-jquery.js> 

Si desea que en el background page se puede hacer referencia a ella desde el fondo de la página mediante una etiqueta de secuencia de comandos desde un recurso relativo en tu complemento

De background.html

<script data-main="scripts/bla" src="scripts/require-jquery.js> 

Si usted quiere que sea incluido en la página del navegador en sí, entonces tienes que utilizar inyección de scripts dinámicos en DOM de la página. Usted tiene acceso al DOM de la página desde content script. Tenga en cuenta que si carga el JavaScript utilizando esta técnica, el complemento JavaScript (desde una página de fondo, secuencia de comandos de contenido o secuencia de comandos emergente) no tendrá acceso a él.

Puede cargar los requirejs desde su extensión utilizando el método chrome.extension.getURL o desde una ubicación alojada en Internet.

var script = document.createElement('script'); 
script.setAttribute("type", "text/javascript"); 
script.setAttribute("async", true); 
script.setAttribute("src", chrome.extension.getURL("require-jquery.js")); 
//Assuming your host supports both http and https 
var head = document.head || document.getElementsByTagName("head")[0] || document.documentElement; 
head.insertBefore(script, head.firstChild) 
+0

Tengo un script de contenido para el cual la manera normal de incluirlo es usando una etiqueta 'script' que tiene un' data-main 'atributo. ¿Cómo puedo especificar el atributo 'data-main' dentro del archivo de manifiesto? – Randomblue

+0

No, no hay forma de agregar una etiqueta de atributo en la secuencia de comandos de contenido si la está incluyendo desde el manifiesto. Puede intentar usar la inyección programática: http://code.google.com/chrome/extensions/content_scripts.html#pi –

+1

En realidad, la inyección programática tampoco funcionará, los mismos problemas (no permitirán atributos en la etiqueta de script). Recomiendo que en lugar de utilizar RequireJS use AMD con Almond.js: https://github.com/jrburke/almond - asegúrese de usar primero un optimizador requireJS como r.js: https://github.com/jrburke/ r.js –

15

aquí está cómo, puede hacerlo en la página de fondo.

En el archivo de manifiesto:

"background": { 
    "scripts": [ "scripts/require.js","scripts/main.js"] 
    }, 

En main.js:

require.config({ 
     baseUrl: "scripts" 
    }); 

    require([ /*...*/ ], function( /*...*/) { 
     /*...*/ 

    }); 

lugar de esto:

<script data-main="scripts/bla" src="scripts/require.js> </script> 

Usted será utilizar este:

<script src="scripts/require-jquery.js ></script> 
<script src="scripts/main.js > </script> 

See this question: Using Require.js without data-main

También puede hacerlo en la página de contenido con esta idea.

Nice Pregunta por cierto.Me gustaron Adam Ayres's respuestas.

+0

Esta debería ser la respuesta aceptada, ya que realmente aborda la pregunta. También tenga en cuenta que si utiliza un plugin RequireJS como jsx, probablemente necesite agregar '" content_security_policy ":" script-src 'self' 'unsafe-eval'; object-src 'self' "' al 'manifest. json' file para que Chrome permita que la extensión use 'eval()'. Esto puede eliminarse en una versión de producción si usa r.js para agrupar todo. – jdunning

1

utilizarlo en un guión contenido que sólo puede incluirlo en el manifest.json como su primera dependencia:

{ 
    "name": "My extension", 
    ... 
    "content_scripts": [ 
    { 
     "matches": ["http://www.google.com/*"], 
     "css": ["mystyles.css"], 
     "js": ["requirejs.js", "myscript.js"] 
    } 
    ], 
    ... 
} 

Será NO contaminar el espacio de nombres global (ventana) de modo no te preocupes por eso; solo está disponible para scripts de extensión.

También en manifest.json tiene que nombrar los archivos que requierenjs podrán usar nombrándolos como "web_accessible_resources", para que esto sea fácil de ponerlos todos en una carpeta (por ejemplo, js /) para que pueda usar un comodín:

{ 
    "name": "My extension", 
    ... 
    "web_accessible_resources": [ 
    "js/*" 
    ], 
    ... 
} 

Y luego, en la secuencia de comandos (por ejemplo MyScript.js) para utilizar RequireJS acaba de pedir las dependencias utilizando chrome.extension.getURL, así:

requirejs([chrome.extension.getURL('js/library')], function(library) { 
    ... 
} 
+0

Cuando uso este método, puedo cargar mis módulos adicionales correctamente, pero luego aparece un error que dice, 'Unbeught ReferenceError: define is not defined'. Lo cual tiene sentido, ¿lograste que esto funcionara? –

2

Editar esto sigue siendo cierto para plain vanilla requieren .js, pero encontró una solución al bifurcar RequireJS

Github: https://github.com/jeroendelau/requirejs
Bower: glorieta instalar RequireJS-para-navegador-extensions

ORIGNAL POSTAL

inyectarlo en el guión de contenido es, con mucho, el más difícil. Y las respuestas anteriores son incompletas o incorrectas.

Antecedentes y emergente:
Ir con la respuesta anterior por @nafis, que van a trabajar

Contenido del guión
Esto es muy difícil, y esta parte de la api description es clave:

Execution environment
Content scripts execute in a special environment called an isolated world. They have access to the DOM of the page they are injected into, but not to any JavaScript variables or functions created by the page. It looks to each content script as if there is no other JavaScript executing on the page it is running on. The same is true in reverse: JavaScript running on the page cannot call any functions or access any variables defined by content scripts.

Intuitivamente esto debe ser correcto
manifest.json

{ 
    "name": "My extension", 
    ... 
    "content_scripts": [ 
    { 
     "matches": ["http://www.google.com/*"], 
     "css": ["mystyles.css"], 
     "js": ["requirejs.js", "myscript.js"] 
    } 
    ], 
    ... 
    "web_accessible_resources": [ 
    "js/*" 
    ], 
... 
} 

MyScript.js

require(["myFancyModule"], function (FM) { 
    ... 
}); 

esto no funcionará

El problema es que RequireJS se procederá a cargar todas sus dependencias mediante la inyección de <script> etiquetas en la cabecera. Estas etiquetas de script se ejecutan en el entorno PAGE, no en el entorno especial EXTENSION. Y esto importa.

  1. dependencias no se pueden cargar desde RequireJS no está cargado en el entorno de la página
  2. Si el propietario del sitio web ha añadido RequireJS alreay, que chocan migh
  3. Usted puede decidir para inyectar require.js en la página, como sugiere @Adam, pero en ese caso ninguna de las funciones de extensión funcionará.almacenamiento, mensajería, solicitud entre sitios son todos no disponible

Así que para que los al trabajo, los módulos cargados por RequireJS necesitan ser inyectado en el medio ambiente extensiones. Es posible usar un complemento requirejs para cambiar el comportamiento de la carga.

Debido a la forma en que esto funciona, la solución es muy poco elegante Y le impide ver las secuencias de comandos en el depurador en las secuencias de comandos. Pero si estás desesperado, funcionará.

MyScript.js

/** 
* Inject the plugin straight into requirejs 
*/ 
define("Injector", { 
    load: function (name, req, onload, config) { 

    //Load the script using XHR, from background 
    var oReq = new XMLHttpRequest(); 
    oReq.addEventListener("load", function() { 

     //Find depenencies in the script, and prepend the 
     //Injector! plugin, forcing the load to go through this 
     //plugin. 
     var modified = getDeps(oReq.response) 

     //have requirejs load the module from text 
     //it will evaluate the define, and process dependencies 
     onload.fromText(modified); 
    }); 
    oReq.open("GET", req.toUrl(name) + ".js"); 
    oReq.send(); 

    //Find dependencies and prepend Injector! 
    function getDeps(script) 
    { 
     //extract the define call, reduced to a single line 
     var defineCall = script.match(/define([\s\S])*?{/m)[0].split("\n").join(""); 
     //extract dependenceis from the call 
     var depsMatch = defineCall.match(/\[([\s\S]*?)\]/); 

     //if there are dependencies, inject the injectors 
     if (depsMatch) 
     { 
     var deps = depsMatch[0]; 
     var replaced = deps.replace(/(\'|\")([\s\S]*?)\1/g, '$1Injector!$2$1'); 
     return script.replace(/define([\s\S]*?)\[[\s\S]*?\]/m, 'define$1' + replaced); 
     } 
     //no dependencies, return script 
     return script; 
    } 
    } 
}); 

/** 
* Call all your dependencies using the plugin 
*/ 
require(["Injector!myFancyModule"], function (FM) { 
     chrome.storage.local.get({something}); 
}); 
Cuestiones relacionadas