From 156ccbc416a6ec8bbc31901dfa3e5d7b9f9e5935 Mon Sep 17 00:00:00 2001 From: imaustink Date: Tue, 20 Jun 2017 09:35:08 -0700 Subject: [PATCH] Fix tag stripping. Fixes #10 --- generators/search-map.js | 10 +++++++--- package.json | 2 +- test.js | 4 ++-- 3 files changed, 10 insertions(+), 6 deletions(-) diff --git a/generators/search-map.js b/generators/search-map.js index bb57d5c..46de680 100644 --- a/generators/search-map.js +++ b/generators/search-map.js @@ -4,7 +4,7 @@ var fs = require('fs'), Q = require('q'), writeFile = Q.denodeify(fs.writeFile), mkdirs = Q.denodeify(require("fs-extra").mkdirs), - unescapeHTML = require("unescape-html"), + striptags = require("striptags"), helpers = require('bit-docs-generate-html/build/make_default_helpers')({}, {}, function(){}, {}); /** @@ -26,8 +26,12 @@ module.exports = function(docMap, siteConfig) { if (docMap.hasOwnProperty(name)) { var docObj = docMap[name]; - var description = helpers.stripMarkdown(docObj.description); - description = unescapeHTML(description); + var description = helpers.makeHtml(docObj.description); + description = helpers.makeLinks(description); + description = striptags(description, + // Allowed tags + ['a', 'em', 'code'] + ); var searchObj = { name: docObj.name, diff --git a/package.json b/package.json index bf775b1..d5728e7 100644 --- a/package.json +++ b/package.json @@ -31,7 +31,7 @@ "lodash": "~4.13.1", "md5": "2.1.0", "steal-tools": "0.16.X", - "unescape-html": "^1.0.0" + "striptags": "^3.0.1" }, "devDependencies": { "mocha": ">= 1.18.0", diff --git a/test.js b/test.js index 88b0852..c67e87a 100644 --- a/test.js +++ b/test.js @@ -15,7 +15,7 @@ var docMap = { "path": "docs/can-canjs/can-core.md" }, "body": "\n## Use\n\nCanJS’s core libraries are the best, most hardened and generally useful modules. \nEach module is part of an independent package, so you\nshould install the ones you use directly:\n\n```\nnpm install can-define can-set can-connect can-component can-stache can-route --save\n```\n\n\nLet’s explore each module a bit more.\n\n## can-compute\n\n[can-compute]s represent an observable value. A compute can contain its\nown value and notify listeners of changes like:\n\n```js\nvar compute = require(\"can-compute\");\n\nvar name = compute(\"Justin\");\n\n// read the value\nname() //-> \"Justin\"\n\nname.on(\"change\", function(ev, newVal, oldVal){\n\tnewVal //-> \"Matthew\"\n\toldVal //-> \"Justin\"\n});\n\nname(\"Matthew\");\n```\n\nMore commonly, a compute derives its value from other observables. The following\n`info` compute derives its value from a `person` map, `hobbies` list, and `age`\ncompute:\n\n```js\nvar DefineMap = require(\"can-define/map/map\"),\n\tDefineList = require(\"can-define/list/list\"),\n\tcompute = require(\"can-compute\");\n\nvar person = new DefineMap({first: \"Justin\", last: \"Meyer\"}),\n\thobbies = new DefineList([\"js\",\"bball\"]),\n\tage = compute(33);\n\nvar info = compute(function(){\n\treturn person.first +\" \"+ person.last+ \" is \"+age()+\n\t\t\"and like \"+hobbies.join(\", \")+\".\";\n});\n\ninfo() //-> \"Justin Meyer is 33 and likes js, bball.\"\n\ninfo.on(\"change\", function(ev, newVal){\n\tnewVal //-> \"Justin Meyer is 33 and likes js.\"\n});\n\nhobbies.pop();\n```\n\n\n## can-define\n\n[can-define/map/map] and [can-define/list/list] allow you to create observable\nmaps and lists with well defined properties. You can\n[can-define.types.propDefinition define a property’s type initial value, enumerability, getter-setters and much more].\nFor example, you can define the behavior of a `Todo` type and a `TodoList` type as follows:\n\n```js\nvar DefineMap = require(\"can-define/map/map\");\nvar DefineList = require(\"can-define/list/list\");\n\nvar Todo = DefineMap.extend({ // A todo has a:\n name: \"string\", // .name that’s a string\n complete: { // .complete that’s\n\ttype: \"boolean\", // a boolean\n\tvalue: false // initialized to false\n }, \n dueDate: \"date\", // .dueDate that’s a date\n get isPastDue(){ // .pastDue that returns if the\n\treturn new Date() > this.dueDate; // dueDate is before now\n },\n toggleComplete: function(){ // .toggleComplete method that\n this.complete = !this.complete; // changes .complete\n }\n});\n\nvar TodoList = DefineList.extend({ // A list of todos: \n \"#\": Todo, // has numeric properties\n // as todos\n\n get completeCount(){ // has .completeCount that\n return this.filter(\"complete\") // returns # of\n\t .length; // complete todos\n }\n});\n```\n\nThis allows you to create a Todo, read its properties, and\ncall back its methods like:\n\n```js\nvar dishes = new Todo({\n\tname: \"do dishes\",\n\t// due yesterday\n\tdueDate: new Date() - 1000 * 60 * 60 * 24\n});\ndishes.name //-> \"do dishes\"\ndishes.isPastDue //-> true\ndishes.complete //-> false\ndishes.toggleComplete() \ndishes.complete //-> true\n```\n\nAnd it allows you to create a `TodoList`, access its items and properties\nlike:\n\n```js\nvar todos = new TodoList( dishes, {name: \"mow lawn\", dueDate: new Date()});\ntodos.length //-> 2\ntodos[0].complete //-> true\ntodos.completeCount //-> 1\n```\n\nThese observables provide the foundation\nfor data connection (models), view-models and even routing in your application.\n\n## can-set\n\n[can-set] models a service layer’s behavior as a [can-set.Algebra set.Algebra]. Once modeled, other libraries such as [can-connect] or [can-fixture] can\nadd a host of functionality like: real-time behavior, performance optimizations, and\nsimulated service layers.\n\nA `todosAlgebra` set algebra for a `GET /api/todos` service might look like:\n\n```js\nvar set = require(\"can-set\");\nvar todosAlgebra = new set.Algebra(\n // specify the unique identifier property on data\n set.prop.id(\"_id\"), \n // specify that completed can be true, false or undefined\n set.prop.boolean(\"complete\"),\n // specify the property that controls sorting\n set.prop.sort(\"orderBy\")\n)\n```\n\nThis assumes that the service:\n\n - Returns data where the unique property name is `_id`:\n ```js\n GET /api/todos\n -> [{_id: 1, name: \"mow lawn\", complete: true},\n {_id: 2, name: \"do dishes\", complete: false}, ...]\n ```\n - Can filter by a `complete` property:\n ```js\n GET /api/todos?complete=false\n -> [{_id: 2, name: \"do dishes\", complete: false}, ...]\n ```\n - Sorts by an `orderBy` property:\n ```js\n GET /api/todos?orderBy=name\n -> [{_id: 2, name: \"do dishes\", complete: false},\n {_id: 1, name: \"mow lawn\", complete: true}]\n ```\n\nIn the next section will use `todoAlgebra` to build a model with [can-connect].\n\n## can-connect\n\n[can-connect] connects a data type, typically a `DefineMap` and its `DefineList`,\nto a service layer. This is often done via the\n[can-connect/can/base-map/base-map] module which bundles many common behaviors\ninto a single api:\n\n```js\nvar baseMap = require(\"can-connect/can/base-map/base-map\"),\n DefineMap = require(\"can-define/map/map\"),\n DefineList = require(\"can-define/list/list\"),\n\tset = require(\"can-set\");\n\nvar Todo = DefineMap.extend({\n\t...\n});\nvar TodosList = DefineMap.extend({\n\t\"#\": Todo,\n\t...\n});\nvar todosAlgebra = new set.Algebra({\n\t...\n});\n\nvar connection = baseMap({\n\turl: \"/api/todos\",\n\tMap: Todo,\n\tList: TodoList,\n\talgebra: todosAlgebra,\n\tname: \"todo\"\n});\n```\n\n`baseMap` extends the `Map` type, in this case, `Todo`, with\nthe ability to make requests to the service layer.\n\n - [can-connect/can/map/map.getList Get a list] of Todos\n ```js\n Todo.getList({complete: true}).then(function(todos){})\n ```\n - [can-connect/can/map/map.get Get] a single Todo\n ```js\n Todo.get({_id: 6}).then(function(todo){})\n ```\n - [can-connect/can/map/map.prototype.save Create] a Todo\n ```js\n var todo = new Todo({name: \"do dishes\", complete: false})\n todo.save().then(function(todo){})\n ```\n - [can-connect/can/map/map.prototype.save Update] an [can-connect/can/map/map.prototype.isNew already created] Todo\n ```js\n todo.complete = true;\n todo.save().then(function(todo){})\n ```\n - [can-connect/can/map/map.prototype.destroy Delete] a Todo\n ```js\n todo.destroy().then(function(todo){})\n ```\n\n[can-connect] is also middleware, so custom connections can\nbe assembled too:\n\n```js\nvar base = require(\"can-connect/base/base\");\nvar dataUrl = require(\"can-connect/data-url/data-url\");\nvar constructor = require(\"can-connect/constructor/constructor\");\nvar map = require(\"can-connect/can/map/map\");\n\nvar options = {\n\turl: \"/api/todos\",\n\tMap: Todo,\n\tList: TodoList,\n\talgebra: todosAlgebra,\n\tname: \"todo\"\n}\nvar connection = map(constructor(dataUrl(base(options))));\n```\n\n## can-stache\n\n[can-stache] provides live binding mustache and handlebars syntax. While\ntemplates should typically be loaded with a module loader like [steal-stache],\nyou can create a template programmatically that lists out todos within a\npromise loaded from `Todo.getList` like:\n\n```js\nvar stache = require(\"can-stache\");\n\n// Creates a template\nvar template = stache(\n\t\"\");\n\n// Calls the template with some data\nvar frag = template({\n\ttodos: Todo.getList({})\n});\n\n// Inserts the result into the page\ndocument.body.appendChild(frag);\n```\n\n[can-stache] templates use magic tags like `{{}}` to control what\ncontent is rendered. The most common forms of those magic tags are:\n\n - [can-stache.tags.escaped {{key}}] - Insert the value at `key` in the page. If `key` is a function or helper, run it and insert the result.\n - [can-stache.tags.section {{#key}}...{{/key}}] - Render the content between magic tags based on some criteria. \n\n[can-stache] templates return document fragments that update whenever\ntheir source data changes.\n\n## can-component\n\n[can-component] creates custom elements with unit-testable view models. It\ncombines a view model created by [can-define/map/map] with a template\ncreated by [can-stache].\n\n```js\nvar Component = require(\"can-component\");\nvar DefineMap = require(\"can-define/map/map\");\nvar stache = require(\"can-stache\");\n\n// Defines the todos-list view model\nvar TodosListVM = DefineMap.extend({\n\t// An initial value that is a promise containing the\n\t// list of all todos.\n\ttodos: {\n\t\tvalue: function(){\n\t\t\treturn Todo.getList({});\n\t\t}\n\t},\n\t// A method that toggles a todo’s complete property\n\t// and updates the todo on the server.\n\ttoggleComplete: function(todo){\n\t\ttodo.complete = !todo.complete;\n\t\ttodo.save();\n\t}\n});\n\nComponent.extend({\n\ttag: \"todos-list\",\n\tViewModel: TodosVM,\n\tview: stache(\n\t\t\"\");\n});\n```\n\n## can-stache-bindings\n\n[can-stache-bindings] provides [can-view-callbacks.attr custom attributes] for\n[can-stache] event and data bindings.\n\nBindings look like:\n\n - `(event)=\"key()\"` for [can-stache-bindings.event event binding].\n - `{prop}=\"key\"` for [can-stache-bindings.toChild one-way binding to a child].\n - `{^prop}=\"key\"` for [can-stache-bindings.toParent one-way binding to a parent].\n - `{(prop)}=\"key\"` for [can-stache-bindings.twoWay two-way binding].\n\nAdding `$` to a binding like `($event)=\"key()\"` changes the binding from the viewModel to the element’s attributes or properties.\n\n[can-stache-bindings.event Event] binding examples:\n\n```html\n\n
  • \n\n\n\n```\n\n[can-stache-bindings.toChild One-way to child] examples:\n\n```html\n\n\n\n\n\n```\n\n[can-stache-bindings.toChild One-way to parent] examples:\n\n```html\n\n\n\n\n\n```\n\n[can-stache-bindings.twoWay Two-way] examples:\n\n```html\n\n\n\n\n\n```\n\n## can-route and can-route-pushstate\n\n[can-route] connects a `DefineMap`’s properties to values in the\nurl. Create a map type, [canjs/doc/can-route.map connect it to the url], and [can-route.ready begin routing] like:\n\n```js\nvar route = require(\"can-route\");\nvar DefineMap = require(\"can-define/map/map\");\n\nvar AppViewModel = DefineMap.extend({\n\tseal: false\n},{\n\t// Sets the default type to string\n\t\"#\": \"string\",\n\ttodoId: \"string\",\n\ttodo: {\n\t\tget: function(){\n\t\t\tif(this.todoId) {\n\t\t\t\treturn Todo.get({_id: this.todoId})\n\t\t\t}\n\t\t}\n\t}\n});\n\nvar appViewModel = new AppViewModel();\nroute.map(appViewModel);\n\nroute.ready();\n```\n\nWhen the url changes, to something like `#!&todoId=5`, so will the\n`appViewModel`’s `todoId` and `todo` property:\n\n```js\nappViewModel.todoId //-> \"5\"\nappViewModel.todo //-> Promise\n```\n\nSimilarly, if `appViewModel`’s `todoId` is set like:\n\n```js\nappViewModel.todoId = 6;\n```\n\nThe hash will be updated:\n\n```js\nwindow.location.hash //-> \"#!&todoId=6\"\n```\n\nThe `route` function can be used to specify pretty routing rules that\ntranslate property changes to a url and a url to property changes. For example,\n\n```js\n// a route like:\nroute(\"todo/{todoId}\");\n\n// and a hash like:\nwindow.location.hash = \"#!todo/7\";\n\n// produces an appViewModel like:\nappViewModel.serialize() //-> {route: \"todo/{todoId}\", todoId: \"7\"}\n```\n\n[can-route-pushstate] adds [pushstate](https://developer.mozilla.org/en-US/docs/Web/API/History_API) support. It\nmixes in this behavior so you just need to import the module:\n\n```js\nvar route = require(\"can-route\");\nrequire(\"can-route-pushstate\");\n```\n\n\n## Want to learn more?\n\nIf you haven’t already, check out the [guides] page on how to learn CanJS. Specifically, you’ll\nwant to check out the [guides/chat] and [guides/todomvc] to learn the basics of using CanJS’s\ncore libraries. After that, check out the [guides/api] on how to use and learn from these API docs.\n\n", - "description": "The best, most hardened and generally useful libraries in CanJS.\n", + "description": 'The best, most hardened and generally useful libraries in CanJS.\n', "name": "can-core", "title": "Core", "type": "page", @@ -63,7 +63,7 @@ describe("bitDocs.generators.searchMap",function(){ }); it("(bitDocs.generators.searchMap.searchMap) Strips HTML from the description", function(done){ - var descriptionShouldEqual = 'The best, most hardened and generally useful libraries in CanJS.'; + var descriptionShouldEqual = 'The best, most hardened and generally useful libraries in CanJS.\n'; docMapPromise.then(function(docMap){ searchMap(docMap, siteConfig).then(function(searchMapResult){ assert.ok(descriptionShouldEqual === searchMapResult['can-core'].description);