mirror of
https://github.com/huhu/rust-search-extension
synced 2024-11-13 23:27:13 +00:00
Integrate macro_railroad_ext (#183)
* Integrate macro_railroad_ext * Fix macro_railroad loading issue * Remove diagram modal `display:none` * Feat * Ignore Cargo.lock file
This commit is contained in:
parent
5f8a35ebe8
commit
82379417a5
13 changed files with 871 additions and 2 deletions
4
.gitignore
vendored
4
.gitignore
vendored
|
@ -2,9 +2,11 @@
|
|||
.DS_Store
|
||||
*.crx
|
||||
*.pem
|
||||
Cargo.lock
|
||||
web-ext-artifacts
|
||||
node_modules
|
||||
target
|
||||
docs/public
|
||||
manifest.json
|
||||
extension/manage/
|
||||
extension/manage/
|
||||
macro_railroad/pkg
|
11
Makefile
11
Makefile
|
@ -9,3 +9,14 @@ assert:
|
|||
# Build manage pages
|
||||
manage:
|
||||
@cd manage && cargo run
|
||||
|
||||
macro-railroad: extension/script/macro-railroad-wasm.js extension/wasm/macro-railroad.wasm
|
||||
|
||||
extension/script/macro-railroad-wasm.js: macro-railroad/pkg/macro-railroad.js
|
||||
cp $< $@
|
||||
|
||||
extension/wasm/macro-railroad.wasm: macro-railroad/pkg/macro-railroad.wasm
|
||||
cp $< $@
|
||||
|
||||
macro-railroad/pkg/macro-railroad.wasm: macro-railroad/Cargo.lock macro-railroad/Cargo.toml macro-railroad/build.rs macro-railroad/src/lib.rs
|
||||
cd macro-railroad && wasm-pack build -t no-modules --out-name macro-railroad && mv pkg/macro-railroad_bg.wasm pkg/macro-railroad.wasm
|
2
core
2
core
|
@ -1 +1 @@
|
|||
Subproject commit 057f688d6e5db163e91ff54dbe42b48f47aa6b95
|
||||
Subproject commit 84c1e30c0f163bf67abd4f0e4b6c15248a65bfab
|
12
extension/assets/fullscreen.svg
Normal file
12
extension/assets/fullscreen.svg
Normal file
|
@ -0,0 +1,12 @@
|
|||
<?xml version="1.0" encoding="iso-8859-1"?>
|
||||
<!-- Generator: Adobe Illustrator 18.1.1, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
|
||||
<svg version="1.1" id="Capa_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
|
||||
viewBox="0 0 32 32" style="enable-background:new 0 0 32 32;" xml:space="preserve">
|
||||
<g>
|
||||
<g>
|
||||
<path style="fill:#010002;" d="M32,26V2H0v24h14v2H8v2h16v-2h-6v-2H32z M2,24V4h28v20H2z"/>
|
||||
<polygon style="fill:#010002;" points="28,14 28,6 20,6"/>
|
||||
<polygon style="fill:#010002;" points="4,22 12,22 4,14"/>
|
||||
</g>
|
||||
</g>
|
||||
</svg>
|
After Width: | Height: | Size: 600 B |
1
extension/assets/options.svg
Normal file
1
extension/assets/options.svg
Normal file
|
@ -0,0 +1 @@
|
|||
<?xml version="1.0" ?><!DOCTYPE svg PUBLIC '-//W3C//DTD SVG 1.1//EN' 'http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd'><svg height="32px" id="Layer_1" style="enable-background:new 0 0 32 32;" version="1.1" viewBox="0 0 32 32" width="32px" xml:space="preserve" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink"><path d="M4,10h24c1.104,0,2-0.896,2-2s-0.896-2-2-2H4C2.896,6,2,6.896,2,8S2.896,10,4,10z M28,14H4c-1.104,0-2,0.896-2,2 s0.896,2,2,2h24c1.104,0,2-0.896,2-2S29.104,14,28,14z M28,22H4c-1.104,0-2,0.896-2,2s0.896,2,2,2h24c1.104,0,2-0.896,2-2 S29.104,22,28,22z"/></svg>
|
After Width: | Height: | Size: 605 B |
430
extension/script/macro-railroad-wasm.js
Normal file
430
extension/script/macro-railroad-wasm.js
Normal file
|
@ -0,0 +1,430 @@
|
|||
let wasm_bindgen;
|
||||
(function() {
|
||||
const __exports = {};
|
||||
let wasm;
|
||||
|
||||
const cachedTextDecoder = new TextDecoder('utf-8', { ignoreBOM: true, fatal: true });
|
||||
|
||||
cachedTextDecoder.decode();
|
||||
|
||||
let cachedUint8Memory0 = new Uint8Array();
|
||||
|
||||
function getUint8Memory0() {
|
||||
if (cachedUint8Memory0.byteLength === 0) {
|
||||
cachedUint8Memory0 = new Uint8Array(wasm.memory.buffer);
|
||||
}
|
||||
return cachedUint8Memory0;
|
||||
}
|
||||
|
||||
function getStringFromWasm0(ptr, len) {
|
||||
return cachedTextDecoder.decode(getUint8Memory0().subarray(ptr, ptr + len));
|
||||
}
|
||||
|
||||
const heap = new Array(32).fill(undefined);
|
||||
|
||||
heap.push(undefined, null, true, false);
|
||||
|
||||
let heap_next = heap.length;
|
||||
|
||||
function addHeapObject(obj) {
|
||||
if (heap_next === heap.length) heap.push(heap.length + 1);
|
||||
const idx = heap_next;
|
||||
heap_next = heap[idx];
|
||||
|
||||
heap[idx] = obj;
|
||||
return idx;
|
||||
}
|
||||
|
||||
function getObject(idx) { return heap[idx]; }
|
||||
|
||||
function dropObject(idx) {
|
||||
if (idx < 36) return;
|
||||
heap[idx] = heap_next;
|
||||
heap_next = idx;
|
||||
}
|
||||
|
||||
function takeObject(idx) {
|
||||
const ret = getObject(idx);
|
||||
dropObject(idx);
|
||||
return ret;
|
||||
}
|
||||
/**
|
||||
*/
|
||||
__exports.start = function() {
|
||||
wasm.start();
|
||||
};
|
||||
|
||||
/**
|
||||
* @returns {any}
|
||||
*/
|
||||
__exports.getRailroadDefaultCss = function() {
|
||||
const ret = wasm.getRailroadDefaultCss();
|
||||
return takeObject(ret);
|
||||
};
|
||||
|
||||
/**
|
||||
* @returns {any}
|
||||
*/
|
||||
__exports.getRailroadDigramCss = function() {
|
||||
const ret = wasm.getRailroadDigramCss();
|
||||
return takeObject(ret);
|
||||
};
|
||||
|
||||
let cachedInt32Memory0 = new Int32Array();
|
||||
|
||||
function getInt32Memory0() {
|
||||
if (cachedInt32Memory0.byteLength === 0) {
|
||||
cachedInt32Memory0 = new Int32Array(wasm.memory.buffer);
|
||||
}
|
||||
return cachedInt32Memory0;
|
||||
}
|
||||
|
||||
const u32CvtShim = new Uint32Array(2);
|
||||
|
||||
const int64CvtShim = new BigInt64Array(u32CvtShim.buffer);
|
||||
|
||||
let WASM_VECTOR_LEN = 0;
|
||||
|
||||
const cachedTextEncoder = new TextEncoder('utf-8');
|
||||
|
||||
const encodeString = (typeof cachedTextEncoder.encodeInto === 'function'
|
||||
? function (arg, view) {
|
||||
return cachedTextEncoder.encodeInto(arg, view);
|
||||
}
|
||||
: function (arg, view) {
|
||||
const buf = cachedTextEncoder.encode(arg);
|
||||
view.set(buf);
|
||||
return {
|
||||
read: arg.length,
|
||||
written: buf.length
|
||||
};
|
||||
});
|
||||
|
||||
function passStringToWasm0(arg, malloc, realloc) {
|
||||
|
||||
if (realloc === undefined) {
|
||||
const buf = cachedTextEncoder.encode(arg);
|
||||
const ptr = malloc(buf.length);
|
||||
getUint8Memory0().subarray(ptr, ptr + buf.length).set(buf);
|
||||
WASM_VECTOR_LEN = buf.length;
|
||||
return ptr;
|
||||
}
|
||||
|
||||
let len = arg.length;
|
||||
let ptr = malloc(len);
|
||||
|
||||
const mem = getUint8Memory0();
|
||||
|
||||
let offset = 0;
|
||||
|
||||
for (; offset < len; offset++) {
|
||||
const code = arg.charCodeAt(offset);
|
||||
if (code > 0x7F) break;
|
||||
mem[ptr + offset] = code;
|
||||
}
|
||||
|
||||
if (offset !== len) {
|
||||
if (offset !== 0) {
|
||||
arg = arg.slice(offset);
|
||||
}
|
||||
ptr = realloc(ptr, len, len = offset + arg.length * 3);
|
||||
const view = getUint8Memory0().subarray(ptr + offset, ptr + len);
|
||||
const ret = encodeString(arg, view);
|
||||
|
||||
offset += ret.written;
|
||||
}
|
||||
|
||||
WASM_VECTOR_LEN = offset;
|
||||
return ptr;
|
||||
}
|
||||
|
||||
function _assertClass(instance, klass) {
|
||||
if (!(instance instanceof klass)) {
|
||||
throw new Error(`expected instance of ${klass.name}`);
|
||||
}
|
||||
return instance.ptr;
|
||||
}
|
||||
/**
|
||||
* Parse the given macro_rules!()-source, returns an SVG and it's preferred width
|
||||
* @param {string} src
|
||||
* @param {DiagramOptions} options
|
||||
* @returns {Diagram}
|
||||
*/
|
||||
__exports.toDiagram = function(src, options) {
|
||||
try {
|
||||
const retptr = wasm.__wbindgen_add_to_stack_pointer(-16);
|
||||
const ptr0 = passStringToWasm0(src, wasm.__wbindgen_malloc, wasm.__wbindgen_realloc);
|
||||
const len0 = WASM_VECTOR_LEN;
|
||||
_assertClass(options, DiagramOptions);
|
||||
wasm.toDiagram(retptr, ptr0, len0, options.ptr);
|
||||
var r0 = getInt32Memory0()[retptr / 4 + 0];
|
||||
var r1 = getInt32Memory0()[retptr / 4 + 1];
|
||||
var r2 = getInt32Memory0()[retptr / 4 + 2];
|
||||
if (r2) {
|
||||
throw takeObject(r1);
|
||||
}
|
||||
return Diagram.__wrap(r0);
|
||||
} finally {
|
||||
wasm.__wbindgen_add_to_stack_pointer(16);
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
*/
|
||||
class Diagram {
|
||||
|
||||
static __wrap(ptr) {
|
||||
const obj = Object.create(Diagram.prototype);
|
||||
obj.ptr = ptr;
|
||||
|
||||
return obj;
|
||||
}
|
||||
|
||||
__destroy_into_raw() {
|
||||
const ptr = this.ptr;
|
||||
this.ptr = 0;
|
||||
|
||||
return ptr;
|
||||
}
|
||||
|
||||
free() {
|
||||
const ptr = this.__destroy_into_raw();
|
||||
wasm.__wbg_diagram_free(ptr);
|
||||
}
|
||||
/**
|
||||
* @returns {bigint}
|
||||
*/
|
||||
get width() {
|
||||
try {
|
||||
const retptr = wasm.__wbindgen_add_to_stack_pointer(-16);
|
||||
wasm.__wbg_get_diagram_width(retptr, this.ptr);
|
||||
var r0 = getInt32Memory0()[retptr / 4 + 0];
|
||||
var r1 = getInt32Memory0()[retptr / 4 + 1];
|
||||
u32CvtShim[0] = r0;
|
||||
u32CvtShim[1] = r1;
|
||||
const n0 = int64CvtShim[0];
|
||||
return n0;
|
||||
} finally {
|
||||
wasm.__wbindgen_add_to_stack_pointer(16);
|
||||
}
|
||||
}
|
||||
/**
|
||||
* @returns {string}
|
||||
*/
|
||||
get svg() {
|
||||
try {
|
||||
const retptr = wasm.__wbindgen_add_to_stack_pointer(-16);
|
||||
wasm.diagram_svg(retptr, this.ptr);
|
||||
var r0 = getInt32Memory0()[retptr / 4 + 0];
|
||||
var r1 = getInt32Memory0()[retptr / 4 + 1];
|
||||
return getStringFromWasm0(r0, r1);
|
||||
} finally {
|
||||
wasm.__wbindgen_add_to_stack_pointer(16);
|
||||
wasm.__wbindgen_free(r0, r1);
|
||||
}
|
||||
}
|
||||
}
|
||||
__exports.Diagram = Diagram;
|
||||
/**
|
||||
*/
|
||||
class DiagramOptions {
|
||||
|
||||
static __wrap(ptr) {
|
||||
const obj = Object.create(DiagramOptions.prototype);
|
||||
obj.ptr = ptr;
|
||||
|
||||
return obj;
|
||||
}
|
||||
|
||||
__destroy_into_raw() {
|
||||
const ptr = this.ptr;
|
||||
this.ptr = 0;
|
||||
|
||||
return ptr;
|
||||
}
|
||||
|
||||
free() {
|
||||
const ptr = this.__destroy_into_raw();
|
||||
wasm.__wbg_diagramoptions_free(ptr);
|
||||
}
|
||||
/**
|
||||
* @returns {boolean}
|
||||
*/
|
||||
get hideInternal() {
|
||||
const ret = wasm.__wbg_get_diagramoptions_hideInternal(this.ptr);
|
||||
return ret !== 0;
|
||||
}
|
||||
/**
|
||||
* @param {boolean} arg0
|
||||
*/
|
||||
set hideInternal(arg0) {
|
||||
wasm.__wbg_set_diagramoptions_hideInternal(this.ptr, arg0);
|
||||
}
|
||||
/**
|
||||
* @returns {boolean}
|
||||
*/
|
||||
get keepGroups() {
|
||||
const ret = wasm.__wbg_get_diagramoptions_keepGroups(this.ptr);
|
||||
return ret !== 0;
|
||||
}
|
||||
/**
|
||||
* @param {boolean} arg0
|
||||
*/
|
||||
set keepGroups(arg0) {
|
||||
wasm.__wbg_set_diagramoptions_keepGroups(this.ptr, arg0);
|
||||
}
|
||||
/**
|
||||
* @returns {boolean}
|
||||
*/
|
||||
get foldCommonTails() {
|
||||
const ret = wasm.__wbg_get_diagramoptions_foldCommonTails(this.ptr);
|
||||
return ret !== 0;
|
||||
}
|
||||
/**
|
||||
* @param {boolean} arg0
|
||||
*/
|
||||
set foldCommonTails(arg0) {
|
||||
wasm.__wbg_set_diagramoptions_foldCommonTails(this.ptr, arg0);
|
||||
}
|
||||
/**
|
||||
* @returns {boolean}
|
||||
*/
|
||||
get showLegend() {
|
||||
const ret = wasm.__wbg_get_diagramoptions_showLegend(this.ptr);
|
||||
return ret !== 0;
|
||||
}
|
||||
/**
|
||||
* @param {boolean} arg0
|
||||
*/
|
||||
set showLegend(arg0) {
|
||||
wasm.__wbg_set_diagramoptions_showLegend(this.ptr, arg0);
|
||||
}
|
||||
/**
|
||||
*/
|
||||
constructor() {
|
||||
const ret = wasm.diagramoptions_new();
|
||||
return DiagramOptions.__wrap(ret);
|
||||
}
|
||||
}
|
||||
__exports.DiagramOptions = DiagramOptions;
|
||||
|
||||
async function load(module, imports) {
|
||||
if (typeof Response === 'function' && module instanceof Response) {
|
||||
if (typeof WebAssembly.instantiateStreaming === 'function') {
|
||||
try {
|
||||
return await WebAssembly.instantiateStreaming(module, imports);
|
||||
|
||||
} catch (e) {
|
||||
if (module.headers.get('Content-Type') != 'application/wasm') {
|
||||
console.warn("`WebAssembly.instantiateStreaming` failed because your server does not serve wasm with `application/wasm` MIME type. Falling back to `WebAssembly.instantiate` which is slower. Original error:\n", e);
|
||||
|
||||
} else {
|
||||
throw e;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const bytes = await module.arrayBuffer();
|
||||
return await WebAssembly.instantiate(bytes, imports);
|
||||
|
||||
} else {
|
||||
const instance = await WebAssembly.instantiate(module, imports);
|
||||
|
||||
if (instance instanceof WebAssembly.Instance) {
|
||||
return { instance, module };
|
||||
|
||||
} else {
|
||||
return instance;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function getImports() {
|
||||
const imports = {};
|
||||
imports.wbg = {};
|
||||
imports.wbg.__wbg_log_97290aafbe6479da = function(arg0, arg1) {
|
||||
console.log(getStringFromWasm0(arg0, arg1));
|
||||
};
|
||||
imports.wbg.__wbindgen_string_new = function(arg0, arg1) {
|
||||
const ret = getStringFromWasm0(arg0, arg1);
|
||||
return addHeapObject(ret);
|
||||
};
|
||||
imports.wbg.__wbg_new_693216e109162396 = function() {
|
||||
const ret = new Error();
|
||||
return addHeapObject(ret);
|
||||
};
|
||||
imports.wbg.__wbg_stack_0ddaca5d1abfb52f = function(arg0, arg1) {
|
||||
const ret = getObject(arg1).stack;
|
||||
const ptr0 = passStringToWasm0(ret, wasm.__wbindgen_malloc, wasm.__wbindgen_realloc);
|
||||
const len0 = WASM_VECTOR_LEN;
|
||||
getInt32Memory0()[arg0 / 4 + 1] = len0;
|
||||
getInt32Memory0()[arg0 / 4 + 0] = ptr0;
|
||||
};
|
||||
imports.wbg.__wbg_error_09919627ac0992f5 = function(arg0, arg1) {
|
||||
try {
|
||||
console.error(getStringFromWasm0(arg0, arg1));
|
||||
} finally {
|
||||
wasm.__wbindgen_free(arg0, arg1);
|
||||
}
|
||||
};
|
||||
imports.wbg.__wbindgen_object_drop_ref = function(arg0) {
|
||||
takeObject(arg0);
|
||||
};
|
||||
imports.wbg.__wbindgen_throw = function(arg0, arg1) {
|
||||
throw new Error(getStringFromWasm0(arg0, arg1));
|
||||
};
|
||||
|
||||
return imports;
|
||||
}
|
||||
|
||||
function initMemory(imports, maybe_memory) {
|
||||
|
||||
}
|
||||
|
||||
function finalizeInit(instance, module) {
|
||||
wasm = instance.exports;
|
||||
init.__wbindgen_wasm_module = module;
|
||||
cachedInt32Memory0 = new Int32Array();
|
||||
cachedUint8Memory0 = new Uint8Array();
|
||||
|
||||
wasm.__wbindgen_start();
|
||||
return wasm;
|
||||
}
|
||||
|
||||
function initSync(bytes) {
|
||||
const imports = getImports();
|
||||
|
||||
initMemory(imports);
|
||||
|
||||
const module = new WebAssembly.Module(bytes);
|
||||
const instance = new WebAssembly.Instance(module, imports);
|
||||
|
||||
return finalizeInit(instance, module);
|
||||
}
|
||||
|
||||
async function init(input) {
|
||||
if (typeof input === 'undefined') {
|
||||
let src;
|
||||
if (typeof document === 'undefined') {
|
||||
src = location.href;
|
||||
} else {
|
||||
src = document.currentScript.src;
|
||||
}
|
||||
input = src.replace(/\.js$/, '_bg.wasm');
|
||||
}
|
||||
const imports = getImports();
|
||||
|
||||
if (typeof input === 'string' || (typeof Request === 'function' && input instanceof Request) || (typeof URL === 'function' && input instanceof URL)) {
|
||||
input = fetch(input);
|
||||
}
|
||||
|
||||
initMemory(imports);
|
||||
|
||||
const { instance, module } = await load(await input, imports);
|
||||
|
||||
return finalizeInit(instance, module);
|
||||
}
|
||||
|
||||
wasm_bindgen = Object.assign(init, __exports);
|
||||
|
||||
})();
|
72
extension/script/macro-railroad.css
Normal file
72
extension/script/macro-railroad.css
Normal file
|
@ -0,0 +1,72 @@
|
|||
div.railroad_container {
|
||||
height: auto;
|
||||
max-height: 100%;
|
||||
max-width: 100%;
|
||||
position: relative;
|
||||
}
|
||||
|
||||
svg.railroad {
|
||||
border: 1px solid grey;
|
||||
}
|
||||
|
||||
div.railroad_modal {
|
||||
z-index: 10000;
|
||||
position: fixed;
|
||||
width: 100vw;
|
||||
height: 100vh;
|
||||
top: 0;
|
||||
left: 0;
|
||||
background: rgba(0, 0, 0, 0.5);
|
||||
visibility: hidden;
|
||||
opacity: 0;
|
||||
transition: opacity 0.5s, visibility 0s 0.5s;
|
||||
}
|
||||
|
||||
div.railroad_modal_content > svg {
|
||||
margin: auto;
|
||||
position: absolute;
|
||||
top: 0;
|
||||
bottom: 0;
|
||||
left: 0;
|
||||
right: 0;
|
||||
max-width: 95vw;
|
||||
max-height: 95vh;
|
||||
border: 2px solid black;
|
||||
}
|
||||
|
||||
div.railroad_modal.railroad_active {
|
||||
opacity: 1;
|
||||
visibility: visible;
|
||||
transition: opacity 0.5s;
|
||||
}
|
||||
|
||||
div.railroad_icons {
|
||||
position: absolute;
|
||||
bottom: 8px;
|
||||
right: 8px;
|
||||
}
|
||||
|
||||
img.railroad_icon {
|
||||
opacity: 0.3;
|
||||
transition: opacity 1s;
|
||||
width: 25px;
|
||||
}
|
||||
|
||||
img.railroad_icon:hover {
|
||||
opacity: 1.0;
|
||||
}
|
||||
|
||||
div.railroad_dropdown_content {
|
||||
border: 1px solid black;
|
||||
visibility: hidden;
|
||||
position: absolute;
|
||||
overflow: auto;
|
||||
z-index: 1;
|
||||
background-color: rgba(240,240,240,0.95);
|
||||
white-space: nowrap;
|
||||
padding: 5px;
|
||||
}
|
||||
|
||||
div.railroad_dropdown_show {
|
||||
visibility: visible;
|
||||
}
|
162
extension/script/macro-railroad.js
Normal file
162
extension/script/macro-railroad.js
Normal file
|
@ -0,0 +1,162 @@
|
|||
document.addEventListener("DOMContentLoaded", async () => {
|
||||
await load();
|
||||
});
|
||||
|
||||
async function load() {
|
||||
if (!isRustDoc()) return;
|
||||
|
||||
await wasm_bindgen(chrome.runtime.getURL('wasm/macro-railroad.wasm'));
|
||||
injectCss();
|
||||
|
||||
for (let macro of document.querySelectorAll('pre.macro')) {
|
||||
let parentNode = macro.parentNode;
|
||||
if (!parentNode) continue;
|
||||
|
||||
const macroSrc = macro.innerText;
|
||||
// The div that the `pre.macro` get's moved into, together with the new diagram nodes
|
||||
let newNode = document.createElement('div');
|
||||
newNode.setAttribute('style', 'width: 100%;');
|
||||
// The container which holds the inline-svg on the page
|
||||
let svgContainer = document.createElement('div');
|
||||
svgContainer.setAttribute('class', 'railroad_container');
|
||||
svgContainer.appendChild(document.createElement('svg'));
|
||||
// Append svg container ahead macro element to prevent noisy overflow.
|
||||
newNode.appendChild(svgContainer);
|
||||
newNode.appendChild(macro);
|
||||
|
||||
let modalContainer = createModal();
|
||||
newNode.appendChild(modalContainer);
|
||||
|
||||
const diagramOptions = new wasm_bindgen.DiagramOptions();
|
||||
let iconsContainer = createIcons(macroSrc, diagramOptions);
|
||||
svgContainer.appendChild(iconsContainer);
|
||||
|
||||
parentNode.appendChild(newNode);
|
||||
updateDiagram(macroSrc, diagramOptions);
|
||||
}
|
||||
}
|
||||
|
||||
// Returns `true` if the document's generator is "rustdoc"
|
||||
function isRustDoc() {
|
||||
let gen = document.querySelector('head > meta[name="generator"]');
|
||||
return gen && gen.getAttribute('content') === 'rustdoc';
|
||||
}
|
||||
|
||||
// Injects the relevant CSS into the document's <head>
|
||||
function injectCss() {
|
||||
let head = document.head;
|
||||
|
||||
let rrCss = document.createElement('style');
|
||||
rrCss.setAttribute('type', 'text/css');
|
||||
rrCss.textContent = wasm_bindgen.getRailroadDefaultCss();
|
||||
head.appendChild(rrCss);
|
||||
|
||||
let mrrCss = document.createElement('style');
|
||||
mrrCss.setAttribute('type', 'text/css');
|
||||
mrrCss.textContent = wasm_bindgen.getRailroadDigramCss();
|
||||
head.appendChild(mrrCss);
|
||||
}
|
||||
|
||||
// The modal to go fullscreen
|
||||
function createModal() {
|
||||
let modalContent = document.createElement('div');
|
||||
modalContent.appendChild(document.createElement('svg'));
|
||||
modalContent.setAttribute('class', 'railroad_modal_content');
|
||||
|
||||
let modalContainer = document.createElement('div');
|
||||
modalContainer.appendChild(modalContent);
|
||||
modalContainer.setAttribute('class', 'railroad_modal');
|
||||
modalContainer.onclick = function () {
|
||||
modalContainer.classList.remove('railroad_active');
|
||||
};
|
||||
|
||||
return modalContainer;
|
||||
}
|
||||
|
||||
// The icons in the lower-right corner, including the options-dialog
|
||||
function createIcons(macroSrc, diagramOptions) {
|
||||
// The icons in the bottom-right corner
|
||||
let iconsContainer = document.createElement('div');
|
||||
iconsContainer.setAttribute('class', 'railroad_icons');
|
||||
|
||||
// The options-thingy and the options
|
||||
let optionsContainer = document.createElement('div');
|
||||
optionsContainer.setAttribute('style', 'position: relative; display: inline');
|
||||
|
||||
// The container that holds the options-list
|
||||
let dropdownContainer = document.createElement('div');
|
||||
dropdownContainer.setAttribute('style', 'position: absolute');
|
||||
dropdownContainer.setAttribute('class', 'railroad_dropdown_content');
|
||||
|
||||
let optionsList = document.createElement('ul');
|
||||
optionsList.setAttribute('style', 'list-style-type: none; padding: 0px; margin: 0px');
|
||||
|
||||
const createOption = function (key, label) {
|
||||
let listItem = document.createElement('li');
|
||||
let inputItem = document.createElement('input');
|
||||
inputItem.setAttribute('type', 'checkbox');
|
||||
// Generate random id for inputItem
|
||||
let randomId = Array.from(Array(8), () => Math.floor(Math.random() * 36).toString(36)).join('');
|
||||
let inputItemId = `railroad_${randomId}`;
|
||||
inputItem.setAttribute('id', inputItemId);
|
||||
inputItem.setAttribute('checked', diagramOptions[key]);
|
||||
inputItem.onchange = () => {
|
||||
diagramOptions[key] = inputItem.checked;
|
||||
updateDiagram(macroSrc, diagramOptions);
|
||||
};
|
||||
|
||||
listItem.appendChild(inputItem);
|
||||
|
||||
let labelItem = document.createElement('label');
|
||||
labelItem.setAttribute('style', 'padding-left: 8px');
|
||||
labelItem.setAttribute('for', inputItemId);
|
||||
labelItem.textContent = label;
|
||||
listItem.appendChild(labelItem);
|
||||
|
||||
return listItem;
|
||||
};
|
||||
optionsList.appendChild(createOption('hideInternal', 'Hide macro-internal rules'));
|
||||
optionsList.appendChild(createOption('keepGroups', 'Keep groups bound'));
|
||||
optionsList.appendChild(createOption('foldCommonTails', 'Fold common sections'));
|
||||
optionsList.appendChild(createOption('showLegend', 'Generate legend'));
|
||||
|
||||
dropdownContainer.appendChild(optionsList);
|
||||
|
||||
let optionsIcon = document.createElement('img');
|
||||
optionsIcon.setAttribute('class', 'railroad_icon');
|
||||
optionsIcon.setAttribute('src', chrome.runtime.getURL('assets/options.svg'));
|
||||
optionsIcon.onclick = function () {
|
||||
dropdownContainer.classList.toggle('railroad_dropdown_show');
|
||||
};
|
||||
optionsContainer.appendChild(optionsIcon);
|
||||
optionsContainer.appendChild(dropdownContainer);
|
||||
iconsContainer.appendChild(optionsContainer);
|
||||
|
||||
// The fullscreen-toggle
|
||||
let fullscreenIcon = document.createElement('img');
|
||||
fullscreenIcon.setAttribute('class', 'railroad_icon');
|
||||
fullscreenIcon.setAttribute('src', chrome.runtime.getURL('assets/fullscreen.svg'));
|
||||
fullscreenIcon.onclick = function () {
|
||||
let modalContainer = document.querySelector('.railroad_modal');
|
||||
modalContainer.classList.add('railroad_active');
|
||||
};
|
||||
iconsContainer.appendChild(fullscreenIcon);
|
||||
return iconsContainer;
|
||||
}
|
||||
|
||||
// The update function, called when options are set and to create the initial diagram
|
||||
function updateDiagram(macroSrc, diagramOptions) {
|
||||
let diagram = wasm_bindgen.toDiagram(macroSrc, diagramOptions);
|
||||
let svgContainer = document.querySelector('div.railroad_container');
|
||||
let modalContent = document.querySelector('div.railroad_modal_content');
|
||||
svgContainer.replaceChild(htmlToElement(diagram.svg), svgContainer.firstChild);
|
||||
svgContainer.setAttribute('style', `max-width: ${diagram.width}px`);
|
||||
modalContent.replaceChild(htmlToElement(diagram.svg), modalContent.firstChild);
|
||||
}
|
||||
|
||||
// Convert plain HTML text to element
|
||||
function htmlToElement(html) {
|
||||
let div = document.createElement('div');
|
||||
div.innerHTML = html;
|
||||
return div.firstChild
|
||||
}
|
BIN
extension/wasm/macro-railroad.wasm
Normal file
BIN
extension/wasm/macro-railroad.wasm
Normal file
Binary file not shown.
31
macro-railroad/Cargo.toml
Normal file
31
macro-railroad/Cargo.toml
Normal file
|
@ -0,0 +1,31 @@
|
|||
[package]
|
||||
name = "macro_railroad_ext"
|
||||
version = "0.1.0"
|
||||
authors = ["Lukas Lueg <lukas.lueg@gmail.com>", "lyshuhow@gmail.com"]
|
||||
build = "build.rs"
|
||||
edition = "2021"
|
||||
publish = false
|
||||
|
||||
[lib]
|
||||
crate-type = ["cdylib"]
|
||||
|
||||
[dependencies]
|
||||
wasm-bindgen = "0.2"
|
||||
railroad = "0.1"
|
||||
macro_railroad = "0.1"
|
||||
|
||||
# The `console_error_panic_hook` crate provides better debugging of panics by
|
||||
# logging them with `console.error`. This is great for development, but requires
|
||||
# all the `std::fmt` and `std::panicking` infrastructure, so isn't great for
|
||||
# code size when deploying. However, we don't actually care all that much about
|
||||
# code-size.
|
||||
console_error_panic_hook = "0.1"
|
||||
|
||||
|
||||
[build-dependencies]
|
||||
built = { version = "0.5", features = ["chrono"], default_features = false }
|
||||
|
||||
[profile.release]
|
||||
# Tell `rustc` to optimize for small code size.
|
||||
opt-level = "s"
|
||||
lto = true
|
14
macro-railroad/build.rs
Normal file
14
macro-railroad/build.rs
Normal file
|
@ -0,0 +1,14 @@
|
|||
extern crate built;
|
||||
|
||||
use std::env;
|
||||
use std::path;
|
||||
|
||||
fn main() {
|
||||
let mut opts = built::Options::default();
|
||||
opts.set_dependencies(true);
|
||||
|
||||
let src = env::var("CARGO_MANIFEST_DIR").unwrap();
|
||||
let dst = path::Path::new(&env::var("OUT_DIR").unwrap()).join("built.rs");
|
||||
built::write_built_file_with_opts(&opts, src.as_ref(), &dst)
|
||||
.expect("Failed to acquire build-time information.");
|
||||
}
|
118
macro-railroad/src/lib.rs
Normal file
118
macro-railroad/src/lib.rs
Normal file
|
@ -0,0 +1,118 @@
|
|||
use railroad::RailroadNode;
|
||||
use wasm_bindgen::prelude::*;
|
||||
|
||||
#[wasm_bindgen]
|
||||
extern "C" {
|
||||
#[wasm_bindgen(js_namespace = console)]
|
||||
fn log(s: &str);
|
||||
}
|
||||
|
||||
#[allow(dead_code)]
|
||||
mod built_info {
|
||||
include!(concat!(env!("OUT_DIR"), "/built.rs"));
|
||||
}
|
||||
|
||||
#[wasm_bindgen(start)]
|
||||
pub fn start() {
|
||||
// Set panic hook to get better error messages if our code ever panics.
|
||||
//
|
||||
// For more details see
|
||||
// https://github.com/rustwasm/console_error_panic_hook#readme
|
||||
std::panic::set_hook(Box::new(console_error_panic_hook::hook));
|
||||
|
||||
log(&format!(
|
||||
"macro_railroad built {} on {} using {}",
|
||||
built_info::BUILT_TIME_UTC,
|
||||
built_info::RUSTC_VERSION,
|
||||
built_info::DEPENDENCIES_STR
|
||||
));
|
||||
}
|
||||
|
||||
#[wasm_bindgen(js_name = getRailroadDefaultCss)]
|
||||
pub fn get_railroad_default_css() -> JsValue {
|
||||
railroad::DEFAULT_CSS.into()
|
||||
}
|
||||
|
||||
#[wasm_bindgen(js_name = getRailroadDigramCss)]
|
||||
pub fn get_railroad_digram_css() -> JsValue {
|
||||
macro_railroad::diagram::CSS.into()
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
#[wasm_bindgen]
|
||||
pub struct DiagramOptions {
|
||||
#[wasm_bindgen(js_name = hideInternal)]
|
||||
pub hide_internal: bool,
|
||||
#[wasm_bindgen(js_name = keepGroups)]
|
||||
pub keep_groups: bool,
|
||||
#[wasm_bindgen(js_name = foldCommonTails)]
|
||||
pub foldcommontails: bool,
|
||||
#[wasm_bindgen(js_name = showLegend)]
|
||||
pub show_legend: bool,
|
||||
}
|
||||
|
||||
#[wasm_bindgen]
|
||||
pub struct Diagram {
|
||||
#[wasm_bindgen(readonly)]
|
||||
pub width: i64,
|
||||
// We can't make svg pub since wasm-bindgen require each public field to be Copy.
|
||||
// See rustwasm/wasm-bindgen#1985 and rustwasm/wasm-bindgen#2775.
|
||||
svg: String,
|
||||
}
|
||||
|
||||
#[wasm_bindgen]
|
||||
impl Diagram {
|
||||
#[wasm_bindgen(getter)]
|
||||
pub fn svg(&self) -> String {
|
||||
self.svg.clone()
|
||||
}
|
||||
}
|
||||
|
||||
#[wasm_bindgen]
|
||||
impl DiagramOptions {
|
||||
#[wasm_bindgen(constructor)]
|
||||
pub fn new() -> Self {
|
||||
DiagramOptions {
|
||||
hide_internal: true,
|
||||
keep_groups: true,
|
||||
foldcommontails: true,
|
||||
show_legend: true,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Default for DiagramOptions {
|
||||
fn default() -> Self {
|
||||
Self::new()
|
||||
}
|
||||
}
|
||||
|
||||
/// Parse the given macro_rules!()-source, returns an SVG and it's preferred width
|
||||
#[wasm_bindgen(js_name = toDiagram)]
|
||||
pub fn to_diagram(src: &str, options: &DiagramOptions) -> Result<Diagram, JsValue> {
|
||||
let macro_rules = macro_railroad::parser::parse(src)
|
||||
.map_err(|e| format!("macro_railroad parse failed: {}", e))?;
|
||||
let mut tree = macro_railroad::lowering::MacroRules::from(macro_rules);
|
||||
|
||||
if options.hide_internal {
|
||||
tree.remove_internal();
|
||||
}
|
||||
if !options.keep_groups {
|
||||
tree.ungroup();
|
||||
}
|
||||
if options.foldcommontails {
|
||||
tree.foldcommontails();
|
||||
}
|
||||
tree.normalize();
|
||||
|
||||
let dia = macro_railroad::diagram::into_diagram(tree, options.show_legend);
|
||||
let mut svg = dia.to_string();
|
||||
if svg.ends_with('\n') {
|
||||
svg.pop();
|
||||
}
|
||||
|
||||
Ok(Diagram {
|
||||
width: dia.width(),
|
||||
svg,
|
||||
})
|
||||
}
|
|
@ -20,6 +20,13 @@ local json = if browser == 'chrome' then
|
|||
.addWebAccessibleResources(
|
||||
resources=utils.js_files('script', ['lib', 'add-search-index']),
|
||||
matches=['*://docs.rs/*', '*://doc.rust-lang.org/*'],
|
||||
).addWebAccessibleResources(
|
||||
resources=['wasm/macro-railroad.wasm', 'assets/fullscreen.svg', 'assets/options.svg'],
|
||||
matches=[
|
||||
'*://docs.rs/*',
|
||||
'*://doc.rust-lang.org/*',
|
||||
'file:///*',
|
||||
],
|
||||
) {
|
||||
description: 'A handy browser extension to search Rust docs and crates, etc in the address bar instantly!',
|
||||
// The production extension public key to get the constant extension id during development.
|
||||
|
@ -29,6 +36,7 @@ else
|
|||
local manifest_v2 = import 'core/manifest.libsonnet';
|
||||
manifest_v2.new(name, keyword, description, version)
|
||||
.addWebAccessibleResources(utils.js_files('script', ['lib', 'add-search-index']))
|
||||
.addWebAccessibleResources(['wasm/macro-railroad.wasm', 'assets/fullscreen.svg', 'assets/options.svg'])
|
||||
.addBackgroundScripts(['migration.js', 'settings.js', 'deminifier.js'])
|
||||
.addBackgroundScripts(utils.js_files('search', ['algorithm', 'book', 'crate', 'attribute', 'caniuse', 'lint']))
|
||||
.addBackgroundScripts(utils.js_files('search/docs', ['base', 'crate-doc', 'rustc']))
|
||||
|
@ -63,4 +71,12 @@ json.addIcons(icons())
|
|||
matches=['*://github.com/rust-lang/rust/blob/master/RELEASES.md*'],
|
||||
js=utils.js_files('script', ['lib', 'rust-lang-release']),
|
||||
css=['script/github.css'],
|
||||
).addContentScript(
|
||||
matches=[
|
||||
'*://docs.rs/*',
|
||||
'*://doc.rust-lang.org/*',
|
||||
'file:///*',
|
||||
],
|
||||
js=utils.js_files('script', ['macro-railroad', 'macro-railroad-wasm']),
|
||||
css=['script/macro-railroad.css'],
|
||||
)
|
||||
|
|
Loading…
Reference in a new issue