diff --git a/appveyor.yml b/appveyor.yml index 363537eb..0cbea41d 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -50,7 +50,7 @@ after_deploy: { cd docs - Add-Content link_branch.json "{`"_gitContribute`":{`"branch`":`"$env:APPVEYOR_REPO_COMMIT`",`"apiSpecFolder`":`"docs/override`"}}" + Add-Content link_branch.json "{`"_gitContribute`":{`"sourceBranch`":`"$env:APPVEYOR_REPO_COMMIT`",`"apiSpecFolder`":`"docs/override`"}}" & docfx metadata & docfx build --globalMetadataFiles link_branch.json if ($lastexitcode -ne 0){ diff --git a/docs/templates/fix_urls/ManagedReference.common.js b/docs/templates/fix_urls/ManagedReference.common.js new file mode 100644 index 00000000..24c160fe --- /dev/null +++ b/docs/templates/fix_urls/ManagedReference.common.js @@ -0,0 +1,256 @@ +// Copyright (c) Microsoft. All rights reserved. Licensed under the MIT license. See LICENSE file in the project root for full license information. +var common = require('./common.js'); +var classCategory = 'class'; +var namespaceCategory = 'ns'; + +exports.transform = function (model) { + + if (!model) return null; + + langs = model.langs; + handleItem(model, model._gitContribute, model._gitUrlPattern); + if (model.children) { + model.children.forEach(function (item) { + handleItem(item, model._gitContribute, model._gitUrlPattern); + }); + } + + if (model.type) { + switch (model.type.toLowerCase()) { + case 'namespace': + model.isNamespace = true; + if (model.children) groupChildren(model, namespaceCategory); + break; + case 'class': + case 'interface': + case 'struct': + case 'delegate': + case 'enum': + model.isClass = true; + if (model.children) groupChildren(model, classCategory); + model[getTypePropertyName(model.type)] = true; + break; + default: + break; + } + } + + return model; +} + +exports.getBookmarks = function (model, ignoreChildren) { + if (!model || !model.type || model.type.toLowerCase() === "namespace") return null; + + var bookmarks = {}; + + if (typeof ignoreChildren == 'undefined' || ignoreChildren === false) { + if (model.children) { + model.children.forEach(function (item) { + bookmarks[item.uid] = common.getHtmlId(item.uid); + if (item.overload && item.overload.uid) { + bookmarks[item.overload.uid] = common.getHtmlId(item.overload.uid); + } + }); + } + } + + // Reference's first level bookmark should have no anchor + bookmarks[model.uid] = ""; + return bookmarks; +} + +exports.groupChildren = groupChildren; +exports.getTypePropertyName = getTypePropertyName; +exports.getCategory = getCategory; + +function groupChildren(model, category) { + if (!model || !model.type) { + return; + } + var typeChildrenItems = getDefinitions(category); + var grouped = {}; + + model.children.forEach(function (c) { + if (c.isEii) { + var type = "eii"; + } else { + var type = c.type.toLowerCase(); + } + if (!grouped.hasOwnProperty(type)) { + grouped[type] = []; + } + // special handle for field + if (type === "field" && c.syntax) { + c.syntax.fieldValue = c.syntax.return; + c.syntax.return = undefined; + } + // special handle for property + if ((type === "property" || type === "attachedproperty") && c.syntax) { + c.syntax.propertyValue = c.syntax.return; + c.syntax.return = undefined; + } + // special handle for event + if ((type === "event" || type === "attachedevent") && c.syntax) { + c.syntax.eventType = c.syntax.return; + c.syntax.return = undefined; + } + grouped[type].push(c); + }) + + var children = []; + for (var key in typeChildrenItems) { + if (typeChildrenItems.hasOwnProperty(key) && grouped.hasOwnProperty(key)) { + var typeChildrenItem = typeChildrenItems[key]; + var items = grouped[key]; + if (items && items.length > 0) { + var item = {}; + for (var itemKey in typeChildrenItem) { + if (typeChildrenItem.hasOwnProperty(itemKey)) { + item[itemKey] = typeChildrenItem[itemKey]; + } + } + item.children = items; + children.push(item); + } + } + } + + model.children = children; +} + +function getTypePropertyName(type) { + if (!type) { + return undefined; + } + var loweredType = type.toLowerCase(); + var definition = getDefinition(loweredType); + if (definition) { + return definition.typePropertyName; + } + + return undefined; +} + +function getCategory(type) { + var classItems = getDefinitions(classCategory); + if (classItems.hasOwnProperty(type)) { + return classCategory; + } + + var namespaceItems = getDefinitions(namespaceCategory); + if (namespaceItems.hasOwnProperty(type)) { + return namespaceCategory; + } + return undefined; +} + +function getDefinition(type) { + var classItems = getDefinitions(classCategory); + if (classItems.hasOwnProperty(type)) { + return classItems[type]; + } + var namespaceItems = getDefinitions(namespaceCategory); + if (namespaceItems.hasOwnProperty(type)) { + return namespaceItems[type]; + } + return undefined; +} + +function getDefinitions(category) { + var namespaceItems = { + "class": { inClass: true, typePropertyName: "inClass", id: "classes" }, + "struct": { inStruct: true, typePropertyName: "inStruct", id: "structs" }, + "interface": { inInterface: true, typePropertyName: "inInterface", id: "interfaces" }, + "enum": { inEnum: true, typePropertyName: "inEnum", id: "enums" }, + "delegate": { inDelegate: true, typePropertyName: "inDelegate", id: "delegates" } + }; + var classItems = { + "constructor": { inConstructor: true, typePropertyName: "inConstructor", id: "constructors" }, + "field": { inField: true, typePropertyName: "inField", id: "fields" }, + "property": { inProperty: true, typePropertyName: "inProperty", id: "properties" }, + "attachedproperty": { inAttachedProperty: true, typePropertyName: "inAttachedProperty", id: "attachedProperties" }, + "method": { inMethod: true, typePropertyName: "inMethod", id: "methods" }, + "event": { inEvent: true, typePropertyName: "inEvent", id: "events" }, + "attachedevent": { inAttachedEvent: true, typePropertyName: "inAttachedEvent", id: "attachedEvents" }, + "operator": { inOperator: true, typePropertyName: "inOperator", id: "operators" }, + "eii": { inEii: true, typePropertyName: "inEii", id: "eii" } + }; + if (category === 'class') { + return classItems; + } + if (category === 'ns') { + return namespaceItems; + } + console.err("category '" + category + "' is not valid."); + return undefined; +} + +function handleItem(vm, gitContribute, gitUrlPattern) { + // get contribution information + vm.docurl = common.getImproveTheDocHref(vm, gitContribute, gitUrlPattern); + vm.sourceurl = common.getViewSourceHref(vm, gitContribute, gitUrlPattern); + + // set to null incase mustache looks up + vm.summary = vm.summary || null; + vm.remarks = vm.remarks || null; + vm.conceptual = vm.conceptual || null; + vm.syntax = vm.syntax || null; + vm.implements = vm.implements || null; + vm.example = vm.example || null; + common.processSeeAlso(vm); + + // id is used as default template's bookmark + vm.id = common.getHtmlId(vm.uid); + if (vm.overload && vm.overload.uid) { + vm.overload.id = common.getHtmlId(vm.overload.uid); + } + + if (vm.supported_platforms) { + vm.supported_platforms = transformDictionaryToArray(vm.supported_platforms); + } + + if (vm.requirements) { + var type = vm.type.toLowerCase(); + if (type == "method") { + vm.requirements_method = transformDictionaryToArray(vm.requirements); + } else { + vm.requirements = transformDictionaryToArray(vm.requirements); + } + } + + if (vm && langs) { + if (shouldHideTitleType(vm)) { + vm.hideTitleType = true; + } else { + vm.hideTitleType = false; + } + + if (shouldHideSubtitle(vm)) { + vm.hideSubtitle = true; + } else { + vm.hideSubtitle = false; + } + } + + function shouldHideTitleType(vm) { + var type = vm.type.toLowerCase(); + return ((type === 'namespace' && langs.length == 1 && (langs[0] === 'objectivec' || langs[0] === 'java' || langs[0] === 'c')) + || ((type === 'class' || type === 'enum') && langs.length == 1 && langs[0] === 'c')); + } + + function shouldHideSubtitle(vm) { + var type = vm.type.toLowerCase(); + return (type === 'class' || type === 'namespace') && langs.length == 1 && langs[0] === 'c'; + } + + function transformDictionaryToArray(dic) { + var array = []; + for (var key in dic) { + if (dic.hasOwnProperty(key)) { + array.push({ "name": key, "value": dic[key] }) + } + } + + return array; + } +} \ No newline at end of file diff --git a/docs/templates/fix_urls/UniversalReference.common.js b/docs/templates/fix_urls/UniversalReference.common.js new file mode 100644 index 00000000..4cd6b744 --- /dev/null +++ b/docs/templates/fix_urls/UniversalReference.common.js @@ -0,0 +1,289 @@ +// Copyright (c) Microsoft. All rights reserved. Licensed under the MIT license. See LICENSE file in the project root for full license information. + +var common = require('./common.js');; +var classCategory = 'class'; +var namespaceCategory = 'ns'; + +exports.transform = function (model) { + if (!model) return + + handleItem(model, model._gitContribute, model._gitUrlPattern); + if (model.children) { + normalizeChildren(model.children).forEach(function (item) { + handleItem(item, model._gitContribute, model._gitUrlPattern); + }); + }; + + if (model.type) { + switch (model.type.toLowerCase()) { + case 'namespace': + model.isNamespace = true; + if (model.children) groupChildren(model, namespaceCategory); + break; + case 'package': + case 'class': + case 'interface': + case 'struct': + case 'delegate': + model.isClass = true; + if (model.children) groupChildren(model, classCategory); + model[getTypePropertyName(model.type)] = true; + break; + case 'enum': + model.isEnum = true; + if (model.children) groupChildren(model, classCategory); + model[getTypePropertyName(model.type)] = true; + break; + default: + break; + } + } + + return model; +} + +exports.getBookmarks = function (model, ignoreChildren) { + if (!model || !model.type || model.type.toLowerCase() === "namespace") return null; + + var bookmarks = {}; + + if (typeof ignoreChildren == 'undefined' || ignoreChildren === false) { + if (model.children) { + normalizeChildren(model.children).forEach(function (item) { + bookmarks[item.uid] = common.getHtmlId(item.uid); + if (item.overload && item.overload.uid) { + bookmarks[item.overload.uid] = common.getHtmlId(item.overload.uid); + } + }); + } + } + + // Reference's first level bookmark should have no anchor + bookmarks[model.uid] = ""; + return bookmarks; +} + +function handleItem(vm, gitContribute, gitUrlPattern) { + // get contribution information + vm.docurl = common.getImproveTheDocHref(vm, gitContribute, gitUrlPattern); + vm.sourceurl = common.getViewSourceHref(vm, gitContribute, gitUrlPattern); + + // set to null incase mustache looks up + vm.summary = vm.summary || null; + vm.remarks = vm.remarks || null; + vm.conceptual = vm.conceptual || null; + vm.syntax = vm.syntax || null; + vm.implements = vm.implements || null; + vm.example = vm.example || null; + common.processSeeAlso(vm); + + // id is used as default template's bookmark + vm.id = common.getHtmlId(vm.uid); + if (vm.overload && vm.overload.uid) { + vm.overload.id = common.getHtmlId(vm.overload.uid); + } + + // concatenate multiple types with `|` + if (vm.syntax) { + var syntax = vm.syntax; + if (syntax.parameters) { + syntax.parameters = syntax.parameters.map(function (p) { + return joinType(p); + }) + syntax.parameters = groupParameters(syntax.parameters); + } + if (syntax.return) { + syntax.return = joinType(syntax.return); + } + } +} + +function joinType(parameter) { + // change type in syntax from array to string + var joinTypeProperty = function (type, key) { + if (!type || !type[0] || !type[0][key]) return null; + var value = type.map(function (t) { + return t[key][0].value; + }).join(' | '); + return [{ + lang: type[0][key][0].lang, + value: value + }]; + }; + if (parameter.type) { + parameter.type = { + name: joinTypeProperty(parameter.type, "name"), + nameWithType: joinTypeProperty(parameter.type, "nameWithType"), + fullName: joinTypeProperty(parameter.type, "fullName"), + specName: joinTypeProperty(parameter.type, "specName") + } + } + return parameter; +} + +function groupParameters(parameters) { + // group parameter with properties + if (!parameters || parameters.length == 0) return parameters; + var groupedParameters = []; + var stack = []; + for (var i = 0; i < parameters.length; i++) { + var parameter = parameters[i]; + parameter.properties = null; + var prefixLength = 0; + while (stack.length > 0) { + var top = stack.pop(); + var prefix = top.id + '.'; + if (parameter.id.indexOf(prefix) == 0) { + prefixLength = prefix.length; + if (!top.parameter.properties) { + top.parameter.properties = []; + } + top.parameter.properties.push(parameter); + stack.push(top); + break; + } + if (stack.length == 0) { + groupedParameters.push(top.parameter); + } + } + stack.push({ id: parameter.id, parameter: parameter }); + parameter.id = parameter.id.substring(prefixLength); + } + while (stack.length > 0) { + top = stack.pop(); + } + groupedParameters.push(top.parameter); + return groupedParameters; +} + +function groupChildren(model, category, typeChildrenItems) { + if (!model || !model.type) { + return; + } + if (!typeChildrenItems) { + var typeChildrenItems = getDefinitions(category); + } + var grouped = {}; + + normalizeChildren(model.children).forEach(function (c) { + if (c.isEii) { + var type = "eii"; + } else { + var type = c.type.toLowerCase(); + } + if (!grouped.hasOwnProperty(type)) { + grouped[type] = []; + } + // special handle for field + if (type === "field" && c.syntax) { + c.syntax.fieldValue = c.syntax.return; + c.syntax.return = undefined; + } + // special handle for property + if (type === "property" && c.syntax) { + c.syntax.propertyValue = c.syntax.return; + c.syntax.return = undefined; + } + // special handle for event + if (type === "event" && c.syntax) { + c.syntax.eventType = c.syntax.return; + c.syntax.return = undefined; + } + grouped[type].push(c); + }) + + var children = []; + for (var key in typeChildrenItems) { + if (typeChildrenItems.hasOwnProperty(key) && grouped.hasOwnProperty(key)) { + var typeChildrenItem = typeChildrenItems[key]; + var items = grouped[key]; + if (items && items.length > 0) { + var item = {}; + for (var itemKey in typeChildrenItem) { + if (typeChildrenItem.hasOwnProperty(itemKey)){ + item[itemKey] = typeChildrenItem[itemKey]; + } + } + item.children = items; + children.push(item); + } + } + } + + model.children = children; +} + +function getTypePropertyName(type) { + if (!type) { + return undefined; + } + var loweredType = type.toLowerCase(); + var definition = getDefinition(loweredType); + if (definition) { + return definition.typePropertyName; + } + + return undefined; +} + +function getCategory(type) { + var classItems = getDefinitions(classCategory); + if (classItems.hasOwnProperty(type)) { + return classCategory; + } + + var namespaceItems = getDefinitions(namespaceCategory); + if (namespaceItems.hasOwnProperty(type)) { + return namespaceCategory; + } + return undefined; +} + +function getDefinition(type) { + var classItems = getDefinitions(classCategory); + if (classItems.hasOwnProperty(type)) { + return classItems[type]; + } + var namespaceItems = getDefinitions(namespaceCategory); + if (namespaceItems.hasOwnProperty(type)) { + return namespaceItems[type]; + } + return undefined; +} + +function getDefinitions(category) { + var namespaceItems = { + "class": { inClass: true, typePropertyName: "inClass", id: "classes" }, + "struct": { inStruct: true, typePropertyName: "inStruct", id: "structs" }, + "interface": { inInterface: true, typePropertyName: "inInterface", id: "interfaces" }, + "enum": { inEnum: true, typePropertyName: "inEnum", id: "enums" }, + "delegate": { inDelegate: true, typePropertyName: "inDelegate", id: "delegates" }, + "package": { inDelegate: true, typePropertyName: "inPackage", id: "packages" } + }; + var classItems = { + "constructor": { inConstructor: true, typePropertyName: "inConstructor", id: "constructors" }, + "field": { inField: true, typePropertyName: "inField", id: "fields" }, + "property": { inProperty: true, typePropertyName: "inProperty", id: "properties" }, + "method": { inMethod: true, typePropertyName: "inMethod", id: "methods" }, + "event": { inEvent: true, typePropertyName: "inEvent", id: "events" }, + "operator": { inOperator: true, typePropertyName: "inOperator", id: "operators" }, + "eii": { inEii: true, typePropertyName: "inEii", id: "eii" }, + "function": { inFunction: true, typePropertyName: "inFunction", id: "functions"}, + "member": { inMember: true, typePropertyName: "inMember", id: "members"} + }; + if (category === 'class') { + return classItems; + } + if (category === 'ns') { + return namespaceItems; + } + console.err("category '" + category + "' is not valid."); + return undefined; +} + +function normalizeChildren(children) { + if (children[0] && children[0].lang && children[0].value) { + return children[0].value; + } + return children; +} \ No newline at end of file diff --git a/docs/templates/fix_urls/common.js b/docs/templates/fix_urls/common.js index df8f8114..64815bad 100644 --- a/docs/templates/fix_urls/common.js +++ b/docs/templates/fix_urls/common.js @@ -32,7 +32,8 @@ function getHtmlId(input) { // Note: the parameter `gitContribute` won't be used in this function function getViewSourceHref(item, gitContribute, gitUrlPattern) { if (!item || !item.source || !item.source.remote) return ''; - return getRemoteUrl(item.source.remote, item.source.startLine - '0' + 1, item._gitContribute, gitUrlPattern); + if (!gitContribute) gitContribute = item._gitContribute; + return getRemoteUrl(item.source.remote, item.source.startLine - '0' + 1, gitContribute, gitUrlPattern); } function getImproveTheDocHref(item, gitContribute, gitUrlPattern) { @@ -71,7 +72,7 @@ var gitUrlPatternItems = { 'generateUrl': function (gitInfo) { var url = normalizeGitUrlToHttps(gitInfo.repo); url = getRepoWithoutGitExtension(url); - url += '/blob' + '/' + gitInfo.branch + '/' + gitInfo.path; + url += '/blob' + '/' + gitInfo.sourceBranch + '/' + gitInfo.path; if (gitInfo.startLine && gitInfo.startLine > 0) { url += '/#L' + gitInfo.startLine; } @@ -181,6 +182,7 @@ function getGitInfo(gitContribute, gitRemote) { } mergeKey(gitContribute, gitRemote, result, 'repo'); mergeKey(gitContribute, gitRemote, result, 'branch'); + mergeKey(gitContribute, gitRemote, result, 'sourceBranch'); mergeKey(gitContribute, gitRemote, result, 'path'); return result;