Extend Build Package

OPS provides build service for convertion as well as validation, using the same build logic on local and cloud build. Here's a list of things we validate in build

  1. relative links
  2. file include
  3. code snippet
  4. metadata
  5. basic markdown validation

While OPS provides basic validation during build, it may comes a need that you may want something different, to be added to it. In this case, OPS provides 3 types of customization.

  1. markdown validation
  2. metadata validation
  3. build process customization

Customized Markdown Validation

We support two types of validation

  1. simple HTML tag validation, e.g. do not allow HTML tags like p or h1 in markdown file (more details)
  2. complex markdown token validation, requires user to write some plugins, e.g. do not allow writing one sentence with multiple line break

Here's an sample for simple markdown validation

{
rules : [
    "plugin-contract-name-1",
    { name: "plugin-contract-name-2", disable: true}
],
tagRules : [
    {
        tagNames: ["p"],
        behavior: "Warning",
        messageFormatter: "Tag {0} is not valid.",
        openingTagOnly: true
    }
]
}

Customized Metadata Validation

This feature is not yet exposed to user for customization. Once you need this feature, please connect with us for feature request. Here's an sample which is currently used by OPS, it validates against the HTML generated from your markdown files.

{
  "title": {
    "type": "string",
    "is_multivalued": false,
    "is_queryable": true,
    "is_required": true,
    "is_visible": false,
    "query_name": null,
    "display_name": null,
    "choice_set": null,
    "description": "The title of the topic in HTML <title> tag. This meta is set as \"is_visible\"=FALSE in order not to show in in <meta> tag. It should only show up in HTML <title> tag."
  },
  "asset_id": {
    "type": "string",
    "is_multivalued": false,
    "is_queryable": true,
    "is_required": true,
    "is_visible": true,
    "query_name": null,
    "display_name": null,
    "choice_set": null,
    "description": "The global unique ID of the content in OPS. This ID will not be changed even this content is moved to another place."
  },
  "internal_document_id": {
    "type": "string",
    "is_multivalued": false,
    "is_queryable": true,
    "is_required": true,
    "is_visible": true,
    "query_name": null,
    "display_name": null,
    "choice_set": null,
    "description": "The unique id of the content in OPS DHS. This ID will be changed once this content is moved to another place.\n\nThis is to be replaced by ms.assetid because assetid is globally unique and not changed even after content file movement. After ms.assetid  is ready, this item is to be removed from this table."
  },
  "locale": {
    "type": "string",
    "is_multivalued": false,
    "is_queryable": true,
    "is_required": true,
    "is_visible": false,
    "query_name": null,
    "display_name": null,
    "choice_set": [
      "cs-cz",
      "da-dk",
      "de-de",
      "el-gr",
      "en-us",
      "es-es",
      "fi-fi",
      "fr-fr",
      "hu-hu",
      "it-it",
      "ja-jp",
      "ko-kr",
      "nb-no",
      "nl-nl",
      "pl-pl",
      "pt-br",
      "pt-pt",
      "ru-ru",
      "sv-se",
      "tr-tr",
      "zh-cn",
      "zh-tw",
      "en-gb",
      "en-ca",
      "fr-ca",
      "en-au",
      "de-at",
      "de-ch",
      "en-ie",
      "es-ar",
      "es-bo",
      "es-cl",
      "es-co",
      "es-cr",
      "es-do",
      "es-ec",
      "es-gt",
      "es-hn",
      "es-mx",
      "es-ni",
      "es-pa",
      "es-pe",
      "es-pr",
      "es-py",
      "es-sv",
      "es-uy",
      "es-ve",
      "fr-be",
      "fr-ch",
      "nl-be",
      "en-za",
      "hi-in",
      "ar-ae",
      "en-bz",
      "en-jm",
      "en-nz",
      "en-ph",
      "en-tt",
      "is-is",
      "lt-lt",
      "ms-my",
      "ro-ro",
      "sk-sk",
      "sl-si",
      "th-th",
      "uk-ua",
      "zh-hk",
      "zh-sg",
      "id-id",
      "vi-vn",
      "ar-sa",
      "he-il",
      "ar-bh",
      "ar-dz",
      "ar-eg",
      "ar-iq",
      "ar-jo",
      "ar-kw",
      "ar-lb",
      "ar-ly",
      "ar-ma",
      "ar-om",
      "ar-qa",
      "ar-sy",
      "ar-tn",
      "ar-ye",
      "bg-bg",
      "ca-es",
      "de-li",
      "de-lu",
      "en-hk",
      "en-id",
      "en-in",
      "en-my",
      "en-sg",
      "en-zw",
      "es-us",
      "et-ee",
      "eu-es",
      "fa-ir",
      "fr-lu",
      "fr-mc",
      "gl-es",
      "hr-ba",
      "hr-hr",
      "it-ch",
      "kk-kz",
      "lv-lv",
      "ms-bn",
      "nn-no",
      "sv-fi",
      "ur-pk",
      "zh-mo",
      "bs-cyrl-ba",
      "bs-latn-ba",
      "fil-ph",
      "ha-latn-ng",
      "iu-latn-ca",
      "kok-in",
      "nso-za",
      "qut-gt",
      "quz-pe",
      "sr-cyrl-cs",
      "sr-latn-cs",
      "uz-latn-uz",
      "te-in",
      "ta-in",
      "gu-in",
      "kn-in",
      "ml-in",
      "mr-in",
      "es-xl",
      "sr-cyrl-rs",
      "sr-latn-rs",
      "hy-am"
    ],
    "description": "The language code of the content."
  },
  "product_family": {
    "type": "string",
    "is_multivalued": false,
    "is_queryable": true,
    "is_required": false,
    "is_visible": false,
    "query_name": null,
    "display_name": null,
    "choice_set": [
      "VS",
      "MSDN",
      "MSCategory",
      "SQL",
      "mref",
      "office",
      "vfp",
      "TechNet",
      "test",
      "EXCHG",
      "PROT",
      "Expression",
      "WS",
      "AX",
      "MAG",
      "EXCHSRVCS",
      "Zurich",
      "LiveServices",
      "RedDog",
      "WinEmbedded",
      "KB",
      "mscatalog",
      "XNAGameStudio",
      "NAV",
      "MSADS",
      "BTS",
      "SpecExplorer",
      "PandP",
      "Surface",
      "OCS",
      "CS",
      "P2W",
      "OHelp",
      "WIT",
      "JUPTR",
      "ORM",
      "Bing",
      "MSN",
      "MSatalog",
      "GP",
      "Win",
      "IEB",
      "Azure",
      "WPS",
      "SC",
      "CRM",
      "MDOP",
      "Security",
      "MDM",
      "USD"
    ],
    "description": "Product family name of the content."
  },
  "product_version": {
    "type": "integer",
    "is_multivalued": false,
    "is_queryable": true,
    "is_required": false,
    "is_visible": false,
    "query_name": null,
    "display_name": null,
    "choice_set": null,
    "description": "Product family version of the content."
  },
  "updated_at": {
    "type": "datetime",
    "is_multivalued": false,
    "is_queryable": true,
    "is_required": true,
    "is_visible": true,
    "query_name": null,
    "display_name": null,
    "choice_set": null,
    "description": "Indicates the latest update time of the content. For git its' the push time."
  },
  "author": {
    "type": "string",
    "is_multivalued": false,
    "is_queryable": true,
    "is_required": true,
    "is_visible": true,
    "query_name": null,
    "display_name": null,
    "choice_set": null,
    "description": "Indicates the person who update the content."
  },
  "redirect_url": {
    "type": "string",
    "is_multivalued": false,
    "is_queryable": true,
    "is_required": false,
    "is_visible": false,
    "query_name": null,
    "display_name": null,
    "choice_set": null,
    "description": "The target URL for redirection."
  },
  "toc_asset_id": {
    "type": "string",
    "is_multivalued": false,
    "is_queryable": false,
    "is_required": false,
    "is_visible": false,
    "query_name": null,
    "display_name": null,
    "choice_set": null,
    "description": "Indicates which toc nodes references to this content."
  },
  "content_git_url": {
    "type": "string",
    "is_multivalued": false,
    "is_queryable": false,
    "is_required": false,
    "is_visible": false,
    "query_name": null,
    "display_name": null,
    "choice_set": null,
    "description": "The MD Git URL that \"contribute\"/\"Edit\" button of live page point to. This is the URL seen by external contributors.\n\nThis meta is used in case Private repo is used for OPS Build while Public repo is used for external contribution.\n\nRepo level info included by this URL is configured by \"git_repository_url_open_to_public_contributors\" (E.g. https://github.com/Microsoft/windows-driver-docs-public), while file name and branch info are fulfilled by OPS Build.\n\nCustomize branch info included by this URL can be configured by \"preferred_branch\" (to come)."
  },
  "original_content_git_url": {
    "type": "string",
    "is_multivalued": false,
    "is_queryable": false,
    "is_required": false,
    "is_visible": true,
    "query_name": null,
    "display_name": null,
    "choice_set": null,
    "description": "\nSource MD file of current page, in format of Git URL. \nIn internal environment, it's also the URL of \"contribute\"/\"Edit\" button."
  },
  "open_to_public_contributors": {
    "type": "boolean",
    "is_multivalued": false,
    "is_queryable": false,
    "is_required": false,
    "is_visible": false,
    "query_name": null,
    "display_name": null,
    "choice_set": null,
    "description": "Indicates this content can be edited by public users or not."
  },
  "breadcrumb_path": {
    "type": "string",
    "is_multivalued": false,
    "is_queryable": false,
    "is_required": false,
    "is_visible": false,
    "query_name": null,
    "display_name": null,
    "choice_set": null,
    "description": "Indicates the URL (without base URL) to get the global toc JSON file."
  },
  "site_name": {
    "type": "string",
    "is_multivalued": false,
    "is_queryable": false,
    "is_required": false,
    "is_visible": true,
    "query_name": null,
    "display_name": null,
    "choice_set": [
      "MSDN",
      "TechNet",
      "VisualStudio",
      "Docs",
      "OPS"
    ],
    "description": "Indicates the site name of current DocSet.\nShow it up in page source as \"ms.sitename\" in order not to impact legacy partners.\nDynamic: by Rendering\nStatic: by Build"
  },
  "area": {
    "type": "string",
    "is_multivalued": false,
    "is_queryable": false,
    "is_required": false,
    "is_visible": false,
    "query_name": null,
    "display_name": null,
    "choice_set": null,
    "description": "Indicates which UI theme is applied to this DocSet in Rendering. "
  },
  "theme": {
    "type": "string",
    "is_multivalued": false,
    "is_queryable": false,
    "is_required": false,
    "is_visible": false,
    "query_name": null,
    "display_name": null,
    "choice_set": null,
    "description": "Indicates which UI theme is applied to this DocSet in Rendering. "
  },
  "is_active": {
    "type": "boolean",
    "is_multivalued": false,
    "is_queryable": false,
    "is_required": false,
    "is_visible": false,
    "query_name": null,
    "display_name": null,
    "choice_set": null,
    "description": "Indicates whether Rendering handle this DocSet / content or not."
  },
  "ROBOTS": {
    "type": "string",
    "is_multivalued": false,
    "is_queryable": true,
    "is_required": false,
    "is_visible": true,
    "query_name": null,
    "display_name": null,
    "choice_set": null,
    "description": "Tells visiting robots whether a content may be indexed, or used to harvest more links."
  },
  "gitcommit": {
    "type": "string",
    "is_multivalued": false,
    "is_queryable": false,
    "is_required": true,
    "is_visible": true,
    "query_name": null,
    "display_name": null,
    "choice_set": null,
    "description": "A way to see what the page exactly look like at the moment of publishing. Build fill 'gitcommit' to DHS and rendering show it on the page."
  },
  "contentlang": {
    "type": "string",
    "is_multivalued": false,
    "is_queryable": false,
    "is_required": true,
    "is_visible": true,
    "query_name": null,
    "display_name": null,
    "choice_set": [
      "cs-cz",
      "da-dk",
      "de-de",
      "el-gr",
      "en-us",
      "es-es",
      "fi-fi",
      "fr-fr",
      "hu-hu",
      "it-it",
      "ja-jp",
      "ko-kr",
      "nb-no",
      "nl-nl",
      "pl-pl",
      "pt-br",
      "pt-pt",
      "ru-ru",
      "sv-se",
      "tr-tr",
      "zh-cn",
      "zh-tw",
      "en-gb",
      "en-ca",
      "fr-ca",
      "en-au",
      "de-at",
      "de-ch",
      "en-ie",
      "es-ar",
      "es-bo",
      "es-cl",
      "es-co",
      "es-cr",
      "es-do",
      "es-ec",
      "es-gt",
      "es-hn",
      "es-mx",
      "es-ni",
      "es-pa",
      "es-pe",
      "es-pr",
      "es-py",
      "es-sv",
      "es-uy",
      "es-ve",
      "fr-be",
      "fr-ch",
      "nl-be",
      "en-za",
      "hi-in",
      "ar-ae",
      "en-bz",
      "en-jm",
      "en-nz",
      "en-ph",
      "en-tt",
      "is-is",
      "lt-lt",
      "ms-my",
      "ro-ro",
      "sk-sk",
      "sl-si",
      "th-th",
      "uk-ua",
      "zh-hk",
      "zh-sg",
      "id-id",
      "vi-vn",
      "ar-sa",
      "he-il",
      "ar-bh",
      "ar-dz",
      "ar-eg",
      "ar-iq",
      "ar-jo",
      "ar-kw",
      "ar-lb",
      "ar-ly",
      "ar-ma",
      "ar-om",
      "ar-qa",
      "ar-sy",
      "ar-tn",
      "ar-ye",
      "bg-bg",
      "ca-es",
      "de-li",
      "de-lu",
      "en-hk",
      "en-id",
      "en-in",
      "en-my",
      "en-sg",
      "en-zw",
      "es-us",
      "et-ee",
      "eu-es",
      "fa-ir",
      "fr-lu",
      "fr-mc",
      "gl-es",
      "hr-ba",
      "hr-hr",
      "it-ch",
      "kk-kz",
      "lv-lv",
      "ms-bn",
      "nn-no",
      "sv-fi",
      "ur-pk",
      "zh-mo",
      "bs-cyrl-ba",
      "bs-latn-ba",
      "fil-ph",
      "ha-latn-ng",
      "iu-latn-ca",
      "kok-in",
      "nso-za",
      "qut-gt",
      "quz-pe",
      "sr-cyrl-cs",
      "sr-latn-cs",
      "uz-latn-uz",
      "te-in",
      "ta-in",
      "gu-in",
      "kn-in",
      "ml-in",
      "mr-in",
      "es-xl",
      "sr-cyrl-rs",
      "sr-latn-rs",
      "hy-am"
    ],
    "description": "Indicates the actual language of current content. It may not be the same as 'locale' ."
  },
  "api_scan": {
    "type": "boolean",
    "is_multivalued": false,
    "is_queryable": false,
    "is_required": false,
    "is_visible": false,
    "query_name": null,
    "display_name": null,
    "choice_set": null,
    "description": "Indicate whether the depot need to API Scan"
  },
  "product": {
    "type": "string",
    "is_multivalued": true,
    "is_queryable": false,
    "is_required": false,
    "is_visible": true,
    "query_name": null,
    "display_name": "Product",
    "choice_set": null,
    "description": "Identifies the Platform in which the API ships.  "
  },
  "topic_type": {
    "type": "string",
    "is_multivalued": true,
    "is_queryable": false,
    "is_required": false,
    "is_visible": true,
    "query_name": null,
    "display_name": "TopicType",
    "choice_set": null,
    "description": "Identifies topic as an API reference topic."
  },
  "api_type": {
    "type": "string",
    "is_multivalued": true,
    "is_queryable": false,
    "is_required": false,
    "is_visible": true,
    "query_name": null,
    "display_name": "APIType",
    "choice_set": null,
    "description": "Identifies type of dependency being documented."
  },
  "api_location": {
    "type": "string",
    "is_multivalued": true,
    "is_queryable": false,
    "is_required": false,
    "is_visible": true,
    "query_name": null,
    "display_name": "APILocation",
    "choice_set": null,
    "description": "Identifies location of dependency."
  },
  "api_name": {
    "type": "string",
    "is_multivalued": true,
    "is_queryable": false,
    "is_required": false,
    "is_visible": true,
    "query_name": null,
    "display_name": "APIName",
    "choice_set": null,
    "description": "Identifies the API name."
  },
  "api_extra_info": {
    "type": "string",
    "is_multivalued": false,
    "is_queryable": false,
    "is_required": false,
    "is_visible": true,
    "query_name": null,
    "display_name": "APIExtraInfo",
    "choice_set": null,
    "description": "Other information which is specific to the API type."
  },
  "target_os": {
    "type": "string",
    "is_multivalued": true,
    "is_queryable": false,
    "is_required": false,
    "is_visible": true,
    "query_name": null,
    "display_name": "TargetOS",
    "choice_set": null,
    "description": "Identifies the targeted OS/platform."
  },
  "depot_name": {
    "type": "string",
    "is_multivalued": false,
    "is_queryable": false,
    "is_required": true,
    "is_visible": true,
    "query_name": null,
    "display_name": null,
    "choice_set": null,
    "description": "The name of the DHS depot.\n  depot_name = product name.docset name"
  },
  "pagetype": {
    "type": "string",
    "is_multivalued": false,
    "is_queryable": false,
    "is_required": false,
    "is_visible": true,
    "query_name": null,
    "display_name": null,
    "choice_set": [
      "Conceptual",
      "Reference",
      "Hub Page"
    ],
    "description": "Indicates the page type of the content.\nS99 to support \"Reference\" and \"Conceptual\" by Build.\nAs for \"Hub Page\", still need investigation on how to generate this meta (and all other meta)."
  },
  "word_count": {
    "type": "integer",
    "is_multivalued": false,
    "is_queryable": false,
    "is_required": false,
    "is_visible": false,
    "query_name": null,
    "display_name": null,
    "choice_set": null,
    "description": "Indicates the word count of the content. It's used to caculate the estimated read time and show it on the page.\nEstimated read time (min) = word_count / 200"
  },
  "publish_version": {
    "type": "string",
    "is_multivalued": false,
    "is_queryable": false,
    "is_required": false,
    "is_visible": false,
    "query_name": null,
    "display_name": null,
    "choice_set": null,
    "description": "JSON serialized dictionary to indicate the publish version of the content, including versions of source repo (commit id, submodule info, etc.) and versions of build service and build tool."
  }
}

Build Process Customization

This feature is not yet exposed to user for customization. Once you need this feature, please connect with us for feature request.