Guest User

Untitled

a guest
Jan 17th, 2019
76
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 4.88 KB | None | 0 0
  1. function forEach(array, action) {
  2. for (var i = 0; i < array.length; i++)
  3. action(array[i]);
  4. }
  5.  
  6. function negate(func) {
  7. return function() {
  8. return !func.apply(null, arguments);
  9. };
  10. }
  11.  
  12. function reduce(combine, base, array) {
  13. forEach(array, function (element) {
  14. base = combine(base, element);
  15. });
  16. return base;
  17. }
  18.  
  19. function count(test, array) {
  20. return reduce(function(total, element) {
  21. return total + (test(element) ? 1 : 0);
  22. }, 0, array);
  23. }
  24.  
  25. function splitParagraph(text) {
  26. function indexOrEnd(character) {
  27. var index = text.indexOf(character);
  28. return index == -1 ? text.length : index;
  29. }
  30.  
  31. function takeNormal() {
  32. var end = reduce(Math.min, text.length,
  33. map(indexOrEnd, ["*", "{"]));
  34. var part = text.slice(0, end);
  35. text = text.slice(end);
  36. return part;
  37. }
  38.  
  39. function takeUpTo(character) {
  40. var end = text.indexOf(character, 1);
  41. if (end == -1)
  42. throw new Error("Missing closing '" + character + "'");
  43. var part = text.slice(1, end);
  44. text = text.slice(end + 1);
  45. return part;
  46. }
  47.  
  48. var fragments = [];
  49.  
  50. while (text != "") {
  51. if (text.charAt(0) == "*")
  52. fragments.push({type: "emphasised",
  53. content: takeUpTo("*")});
  54. else if (text.charAt(0) == "{")
  55. fragments.push({type: "footnote",
  56. content: takeUpTo("}")});
  57. else
  58. fragments.push({type: "normal",
  59. content: takeNormal()});
  60. }
  61. return fragments;
  62. }
  63.  
  64. function processParagraph(paragraph) {
  65. var header = 0;
  66. while (paragraph.charAt(0) == "%") {
  67. paragraph = paragraph.slice(1);
  68. header++;
  69. }
  70.  
  71. return {type: (header == 0 ? "p" : "h" + header),
  72. content: splitParagraph(paragraph)};
  73. }
  74.  
  75. function extractFootnotes(paragraphs) {
  76. var footnotes = [];
  77. var currentNote = 0;
  78.  
  79. function replaceFootnote(fragment) {
  80. if (fragment.type == "footnote") {
  81. currentNote++;
  82. footnotes.push(fragment);
  83. fragment.number = currentNote;
  84. return {type: "reference", number: currentNote};
  85. }
  86. else {
  87. return fragment;
  88. }
  89. }
  90.  
  91. forEach(paragraphs, function(paragraph) {
  92. paragraph.content = map(replaceFootnote,
  93. paragraph.content);
  94. });
  95.  
  96. return footnotes;
  97. }
  98.  
  99. function link(target, text) {
  100. return tag("a", [text], {href: target});
  101. }
  102.  
  103. function htmlDoc(title, bodyContent) {
  104. return tag("html", [tag("head", [tag("title", [title])]),
  105. tag("body", bodyContent)]);
  106. }
  107.  
  108. function escapeHTML(text) {
  109. var replacements = [[/&/g, "&"], [/"/g, """],
  110. [/</g, "<"], [/>/g, ">"]];
  111. forEach(replacements, function(replace) {
  112. text = text.replace(replace[0], replace[1]);
  113. });
  114. return text;
  115. }
  116.  
  117. function renderHTML(element) {
  118. var pieces = [];
  119.  
  120. function renderAttributes(attributes) {
  121. var result = [];
  122. if (attributes) {
  123. for (var name in attributes)
  124. result.push(" " + name + "="" +
  125. escapeHTML(attributes[name]) + """);
  126. }
  127. return result.join("");
  128. }
  129.  
  130. function render(element) {
  131. // Text node
  132. if (typeof element == "string") {
  133. pieces.push(escapeHTML(element));
  134. }
  135. // Empty tag
  136. else if (!element.content || element.content.length == 0) {
  137. pieces.push("<" + element.name +
  138. renderAttributes(element.attributes) + "/>");
  139. }
  140. // Tag with content
  141. else {
  142. pieces.push("<" + element.name +
  143. renderAttributes(element.attributes) + ">");
  144. forEach(element.content, render);
  145. pieces.push("</" + element.name + ">");
  146. }
  147. }
  148.  
  149. render(element);
  150. return pieces.join("");
  151. }
  152.  
  153. function footnote(number) {
  154. return tag("sup", [link("#footnote" + number,
  155. String(number))]);
  156. }
  157.  
  158. function renderFragment(fragment) {
  159. if (fragment.type == "reference")
  160. return footnote(fragment.number);
  161. else if (fragment.type == "emphasised")
  162. return tag("em", [fragment.content]);
  163. else if (fragment.type == "normal")
  164. return fragment.content;
  165. }
  166.  
  167. function renderFootnote(footnote) {
  168. var anchor = tag("a", [], {name: "footnote" + footnote.number});
  169. var number = "[" + footnote.number + "] ";
  170. return tag("p", [tag("small", [anchor, number,
  171. footnote.content])]);
  172. }
  173.  
  174. function tag(name, content, attributes) {
  175. return {name: name, attributes: attributes, content: content};
  176. }
  177.  
  178. function renderParagraph(paragraph) {
  179. return tag(paragraph.type, map(renderFragment, paragraph.content));
  180. }
  181.  
  182. function map(func, array) {
  183. var result = [];
  184. forEach(array, function (element) {
  185. result.push(func(element));
  186. });
  187. return result;
  188. }
  189.  
  190. function renderFile(file, title) {
  191. var paragraphs = map(processParagraph, file.split("nn"));
  192. var footnotes = map(renderFootnote, extractFootnotes(paragraphs));
  193. var body = map(renderParagraph, paragraphs).concat(footnotes);
  194. return renderHTML(htmlDoc(title, body));
  195. }
  196.  
  197. viewHTML(renderFile(recluseFile(), "The Book of Programming"));
Add Comment
Please, Sign In to add comment