notebook | , replace core requirement | Cell 6 | Search

This code provides a function to statically replace dynamic imports in code by analyzing the Abstract Syntax Tree (AST) and substituting them with predefined templates. It leverages a custom importer module and transpile function to achieve this transformation.

Run example

npm run import -- "replace notebook import"

replace notebook import

var importer = require('../Core')
var {selectAst} = importer.import("select code tree")
var {transpile} = importer.import("transpile code")
var niceName = importer.import("rename cell to nice name")
var {htmlToTree} = importer.import("html to tree")

var IMPORT_CALLS = `//CallExpression[
./*/Identifier[@name="import" or @name="importNotebook"]]`

function getImportTemplate(imports) {
    throw new Error('TODO: multiple import template')
}

function replaceImport("ctx") {
    var str = selectAst([`./Literal/@value`], ctx)[0]
    if(!str) {
        throw new Error(`Error: dynamic include ${ctx.ownerDocument.toString(ctx)}, TODO: include Core`)
    }
    var result = importer.interpret(str)
    if(Array.isArray(result)) {
        template = getImportTemplate(imports)
    } else {
        template = selectAst([`//CallExpression`], `require("./${niceName(result)}")`)[0]
    }
    var parent = ctx.parentNode
    parent.replaceChild(template, ctx)
    template.setAttribute('parent-attr', 'init')
}

function replaceImports(code) {
    return transpile([
        [IMPORT_CALLS, replaceImport]
    ], code)
}

module.exports = {
    replaceImports
}

What the code could have been:

// Import dependencies
const { selectAst, transpile, htmlToTree, renameCellToNiceName } = require('../Core');

// Regular expression for import calls
const IMPORT_CALLS = /\/\/CallExpression\[\.\*\/Identifier\[(@name="import" or @name="importNotebook")\]\]/;

/**
 * Generates an import template from an array of imports.
 * 
 * @param {Array} imports - The array of imports.
 * @returns {string} The import template.
 */
function getImportTemplate(imports) {
    // If there's only one import, return a single import template.
    if (imports.length === 1) {
        return `require("./${renameCellToNiceName(imports[0])}")`;
    }

    // If there are multiple imports, throw an error as this function is not implemented.
    throw new Error('TODO: multiple import template');
}

/**
 * Replaces an import call with a template.
 * 
 * @param {Object} ctx - The context of the import call.
 */
function replaceImport(ctx) {
    // Select the value of the import call.
    const str = selectAst(['./Literal/@value'], ctx)[0];

    // If the value is empty, throw an error.
    if (!str) {
        throw new Error(`Error: dynamic include ${ctx.ownerDocument.toString(ctx)}`);
    }

    // Interpret the import call.
    const result = selectHtml('require("./${niceName(${str})}")');
    if (Array.isArray(result)) {
        // If the result is an array, generate a template from it.
        const imports = result.map(item => selectAttribute(item, 'value'));
        const template = getImportTemplate(imports);
    } else {
        // If the result is not an array, select the call expression and rename it to a nice name.
        const parent = ctx.parentNode;
        const template = selectAst(['//CallExpression'], result)[0];
        template.setAttribute('parent-attr', 'init');
        parent.replaceChild(template, ctx);
    }
}

/**
 * Replaces all import calls in the given code.
 * 
 * @param {string} code - The code to replace import calls in.
 * @returns {string} The code with import calls replaced.
 */
function replaceImports(code) {
    return transpile([
        [IMPORT_CALLS, replaceImport]
    ], code);
}

module.exports = {
    replaceImports
};

// Helper function to select a value from an HTML element.
function selectValue(element) {
    return element.querySelector('value');
}

// Helper function to select a value from an HTML element.
function selectAttribute(element, name) {
    return element.getAttribute(name);
}

// Helper function to select an HTML element.
function selectHtml(str) {
    return htmlToTree(str);
}

This code defines a function to replace dynamic imports in code with static imports based on a template.

Here's a breakdown:

  1. Imports:

  2. IMPORT_CALLS Constant:

  3. getImportTemplate Function:

  4. replaceImport Function:

  5. replaceImports Function:

  6. Module Exports: