84 lines
3.0 KiB
JavaScript
84 lines
3.0 KiB
JavaScript
/*
|
|
* Copyright (C) 2015 - present Instructure, Inc.
|
|
*
|
|
* This file is part of Canvas.
|
|
*
|
|
* Canvas is free software: you can redistribute it and/or modify it under
|
|
* the terms of the GNU Affero General Public License as published by the Free
|
|
* Software Foundation, version 3 of the License.
|
|
*
|
|
* Canvas is distributed in the hope that it will be useful, but WITHOUT ANY
|
|
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
|
|
* A PARTICULAR PURPOSE. See the GNU Affero General Public License for more
|
|
* details.
|
|
*
|
|
* You should have received a copy of the GNU Affero General Public License along
|
|
* with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
*/
|
|
|
|
// handlebars-loader wants to know about every helper we have, and uses
|
|
// a file convention to autofind them. Since we don't match that
|
|
// convention, we need to specify which helpers are ones it should
|
|
// count on being present (ones defined in handlebars_helpers).
|
|
// We'll then make sure modules requiring a jst file have a dependency
|
|
// on handlebars_helpers built in, since they self-register with handlebars
|
|
// runtime that should be ok.
|
|
|
|
const fs = require('fs')
|
|
const path = require('path')
|
|
const coffee = require('coffee-script')
|
|
|
|
function loadHelpersAST () {
|
|
const filename = path.join(__dirname, '..', 'app/coffeescripts/handlebars_helpers.coffee')
|
|
const source = fs.readFileSync(filename, 'utf8')
|
|
return coffee.nodes(source)
|
|
}
|
|
|
|
// we're looking in the helpers AST for the for loop that goes through a javascript
|
|
// object (the "source" object) and calls "registerHelper" with each property
|
|
// We want to make those same properties into "known" helpers.
|
|
function isHandlebarsAssignmentNode (node) {
|
|
return node.body.contains(childNode =>
|
|
childNode.constructor.name === 'Call' &&
|
|
childNode.variable.base.value === 'Handlebars' &&
|
|
childNode.variable.contains(registerNode =>
|
|
registerNode.constructor.name === 'Access' &&
|
|
registerNode.name.value === 'registerHelper'
|
|
)
|
|
)
|
|
}
|
|
|
|
function findHelperNodes (helpersAST) {
|
|
let helpersCollection = null
|
|
helpersAST.traverseChildren(true, child => {
|
|
if (child.constructor.name === 'For') {
|
|
if (isHandlebarsAssignmentNode(child)) {
|
|
helpersCollection = child.source.base.properties
|
|
return false
|
|
}
|
|
}
|
|
})
|
|
return helpersCollection
|
|
}
|
|
|
|
// given an array of nodes (which are functions assigned to property names),
|
|
// return an array of property names in the "knownHelpers" query format for
|
|
// the handlebars loader.
|
|
function buildQueryStringElements (helperNodes) {
|
|
const queryElements = []
|
|
helperNodes.forEach(helper => {
|
|
const helperName = helper.variable.base.value
|
|
queryElements.push(`knownHelpers[]=${helperName}`)
|
|
})
|
|
return queryElements
|
|
}
|
|
|
|
module.exports = {
|
|
queryString() {
|
|
const helpersAST = loadHelpersAST()
|
|
const helpersCollection = findHelperNodes(helpersAST)
|
|
const queryElements = buildQueryStringElements(helpersCollection)
|
|
return queryElements.join('&')
|
|
}
|
|
}
|