diff options
| -rw-r--r-- | Dockerfile | 4 | ||||
| -rw-r--r-- | docker-compose-test.yaml | 41 | ||||
| -rw-r--r-- | docker-compose.yaml | 39 | ||||
| -rw-r--r-- | model.js | 62 | ||||
| -rw-r--r-- | package-lock.json | 485 | ||||
| -rw-r--r-- | package.json | 1 | ||||
| -rw-r--r-- | put_in_db.js | 26 | ||||
| -rwxr-xr-x | server.js | 144 | ||||
| -rw-r--r-- | static/about.html | 12 | ||||
| -rw-r--r-- | views/archive.ejs | 4 | ||||
| -rw-r--r-- | views/index.ejs | 13 | ||||
| -rw-r--r-- | views/rss_feed.pug | 21 | ||||
| -rw-r--r-- | views/rss_feed_v2.pug | 22 | 
13 files changed, 818 insertions, 56 deletions
| @@ -3,7 +3,7 @@ RUN apk add openssl  WORKDIR /certs  RUN openssl req -nodes -new -x509 -subj="/C=US/ST=Denial/L=springfield/O=Dis/CN=localhost" -keyout server.key -out server.cert -FROM node:lts-alpine3.13 +FROM node:lts-alpine3.15  COPY --from=certbuilder /certs/ /certs  COPY ./package.* /server/  RUN cd /server && npm install --production @@ -11,6 +11,6 @@ COPY ./css /server/css/  COPY ./views /server/views/  COPY ./static /server/static/  COPY ./mds /server/mds/ -COPY ./server.js /server/ +COPY ./*.js /server/  ENTRYPOINT ["/server/server.js"]  EXPOSE 9000 diff --git a/docker-compose-test.yaml b/docker-compose-test.yaml index 73981ef..fceb9b9 100644 --- a/docker-compose-test.yaml +++ b/docker-compose-test.yaml @@ -1,11 +1,12 @@  version: "3.7"  services: -  web: -    image: web +  blog: +    image: blog      build: -      context: ./ +      context: .      networks: -      - webnet +      - blognet +      - dbnet      ports:        - "19009:9000"      cap_drop: @@ -13,5 +14,35 @@ services:      environment:        - SERVER_DEPLOYMENT_TYPE=test        - SERVER_LISTEN_PORT=9000 +    depends_on: +      - mongo +    secrets: +      - mongo_user +      - mongo_pass +  mongo: +    image: mongo:5.0 +    networks: +      - dbnet +    restart: on-failure +    ports: +      - "127.0.0.1:27117:27017" +      - "127.0.0.1:27118:27018" +      - "127.0.0.1:27119:27019" +    volumes: +      - blog-data:/data/db +    environment: +      - MONGO_INITDB_ROOT_USERNAME_FILE=/run/secrets/mongo_user +      - MONGO_INITDB_ROOT_PASSWORD_FILE=/run/secrets/mongo_pass +    secrets: +      - mongo_user +      - mongo_pass  networks: -  webnet: +  blognet: +  dbnet: +volumes: +  blog-data: +secrets: +  mongo_user: +    file: ./mongo_secrets/mongo_user +  mongo_pass: +    file: ./mongo_secrets/mongo_pass diff --git a/docker-compose.yaml b/docker-compose.yaml index 5f3e217..79e5d0c 100644 --- a/docker-compose.yaml +++ b/docker-compose.yaml @@ -1,11 +1,12 @@  version: "3.7"  services: -  web: -    image: web +  blog: +    image: blog      build:        context: ./      networks: -      - webnet +      - blognet +      - dbnet      restart: unless-stopped      ports:        - "9000:9000" @@ -16,5 +17,35 @@ services:      environment:        - SERVER_DEPLOYMENT_TYPE=deployment        - SERVER_LISTEN_PORT=9000 +    depends_on: +      - mongo +    secrets: +      - mongo_user +      - mongo_pass +  mongo: +    image: mongo:5.0 +    networks: +      - dbnet +    restart: on-failure +    ports: +      - "127.0.0.1:27117:27017" +      - "127.0.0.1:27118:27018" +      - "127.0.0.1:27119:27019" +    volumes: +      - blog-data:/data/db +    environment: +      - MONGO_INITDB_ROOT_USERNAME_FILE=/run/secrets/mongo_user +      - MONGO_INITDB_ROOT_PASSWORD_FILE=/run/secrets/mongo_pass +    secrets: +      - mongo_user +      - mongo_pass  networks: -  webnet: +  blognet: +  dbnet: +volumes: +  blog-data: +secrets: +  mongo_user: +    file: ./mongo_secrets/mongo_user +  mongo_pass: +    file: ./mongo_secrets/mongo_pass diff --git a/model.js b/model.js new file mode 100644 index 0000000..dde3913 --- /dev/null +++ b/model.js @@ -0,0 +1,62 @@ +"use strict"; + +const fs = require("fs"); +const path = require("path"); +const mongoose = require("mongoose"); +const Schema = mongoose.Schema; +mongoose.Promise = global.Promise; +const db = {}; +db.mongoose = mongoose; +const db_pass = fs.readFileSync("/run/secrets/mongo_pass").toString(); +const db_user = fs.readFileSync("/run/secrets/mongo_user").toString(); +db.url = "mongodb://" + db_user + ":" + db_pass + "@mongo:27017"; + +const BlogPostSchema = new Schema({ +  title: { type: String, required: true, trim: true }, +  slug: { type: String, required: true, lowercase: true, trim: true }, +  body: { type: String, required: true }, +  teaser: { type: String, required: true }, +  keywords: { type: Array, required: true }, +  lastUpdatedAt: { type: Number }, +}); + +// a simple hook to update the timestamp(lastUpdatedAt) on update +BlogPostSchema.pre("save", function (next) { +  this.lastUpdatedAt = Date.now(); +  next(); +}); + +function dbInit() { +  db.mongoose +    .connect(db.url, { useNewUrlParser: true, useUnifiedTopology: true }) +    .then(() => { +      console.log("successfully connected to db"); +    }) +    .catch((err) => { +      console.log("cannot connect to the database: ", err); +      process.exit(1); +    }); +} + +function populateDB(model) { +  let filePaths = fs.readdirSync(path.join(__dirname, "mds")); +  filePaths.forEach((fileName) => { +    let fileContent = fs +      .readFileSync(path.join(__dirname, "mds", fileName), "utf-8") +      .toString(); +    let newBlogPost = new model({ +      title: fileName, +      slug: fileName, +      body: fileContent, +      teaser: fileName, +      keywords: ["kw1", "kw2"], +    }); +    newBlogPost.save(); +  }); +} + +module.exports = { +  blogPost: mongoose.model("BlogPost", BlogPostSchema), +  dbInit: dbInit, +  populateDB: populateDB, +}; diff --git a/package-lock.json b/package-lock.json index c111ea8..aa9d629 100644 --- a/package-lock.json +++ b/package-lock.json @@ -20,6 +20,7 @@          "markdown-it-highlightjs": "^3.4.0",          "markdown-it-multimd-table": "^4.0.2",          "markdown-it-texmath": "^0.7.0", +        "mongoose": "^6.2.8",          "morgan": "^1.10.0",          "pug": "^3.0.2",          "spdy": "^4.0.2" @@ -176,6 +177,25 @@          "node": ">= 6"        }      }, +    "node_modules/@types/node": { +      "version": "17.0.23", +      "resolved": "https://registry.npmjs.org/@types/node/-/node-17.0.23.tgz", +      "integrity": "sha512-UxDxWn7dl97rKVeVS61vErvw086aCYhDLyvRQZ5Rk65rZKepaFdm53GeqXaKBuOhED4e9uWq34IC3TdSdJJ2Gw==" +    }, +    "node_modules/@types/webidl-conversions": { +      "version": "6.1.1", +      "resolved": "https://registry.npmjs.org/@types/webidl-conversions/-/webidl-conversions-6.1.1.tgz", +      "integrity": "sha512-XAahCdThVuCFDQLT7R7Pk/vqeObFNL3YqRyFZg+AqAP/W1/w3xHaIxuW7WszQqTbIBOPRcItYJIou3i/mppu3Q==" +    }, +    "node_modules/@types/whatwg-url": { +      "version": "8.2.1", +      "resolved": "https://registry.npmjs.org/@types/whatwg-url/-/whatwg-url-8.2.1.tgz", +      "integrity": "sha512-2YubE1sjj5ifxievI5Ge1sckb9k/Er66HyR2c+3+I6VDUUg1TLPdYYTEbQ+DjRkS4nTxMJhgWfSfMRD2sl2EYQ==", +      "dependencies": { +        "@types/node": "*", +        "@types/webidl-conversions": "*" +      } +    },      "node_modules/abab": {        "version": "2.0.5",        "resolved": "https://registry.npmjs.org/abab/-/abab-2.0.5.tgz", @@ -376,6 +396,25 @@        "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz",        "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw=="      }, +    "node_modules/base64-js": { +      "version": "1.5.1", +      "resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.5.1.tgz", +      "integrity": "sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==", +      "funding": [ +        { +          "type": "github", +          "url": "https://github.com/sponsors/feross" +        }, +        { +          "type": "patreon", +          "url": "https://www.patreon.com/feross" +        }, +        { +          "type": "consulting", +          "url": "https://feross.org/support" +        } +      ] +    },      "node_modules/basic-auth": {        "version": "2.0.1",        "resolved": "https://registry.npmjs.org/basic-auth/-/basic-auth-2.0.1.tgz", @@ -421,6 +460,40 @@        "resolved": "https://registry.npmjs.org/browser-process-hrtime/-/browser-process-hrtime-1.0.0.tgz",        "integrity": "sha512-9o5UecI3GhkpM6DrXr69PblIuWxPKk9Y0jHBRhdocZ2y7YECBFCsHm79Pr3OyR2AvjhDkabFJaDJMYRazHgsow=="      }, +    "node_modules/bson": { +      "version": "4.6.2", +      "resolved": "https://registry.npmjs.org/bson/-/bson-4.6.2.tgz", +      "integrity": "sha512-VeJKHShcu1b/ugl0QiujlVuBepab714X9nNyBdA1kfekuDGecxgpTA2Z6nYbagrWFeiIyzSWIOzju3lhj+RNyQ==", +      "dependencies": { +        "buffer": "^5.6.0" +      }, +      "engines": { +        "node": ">=6.9.0" +      } +    }, +    "node_modules/buffer": { +      "version": "5.7.1", +      "resolved": "https://registry.npmjs.org/buffer/-/buffer-5.7.1.tgz", +      "integrity": "sha512-EHcyIPBQ4BSGlvjB16k5KgAJ27CIsHY/2JBmCRReo48y9rQ3MaUzWX3KVlBa4U7MyX02HdVj0K7C3WaB3ju7FQ==", +      "funding": [ +        { +          "type": "github", +          "url": "https://github.com/sponsors/feross" +        }, +        { +          "type": "patreon", +          "url": "https://www.patreon.com/feross" +        }, +        { +          "type": "consulting", +          "url": "https://feross.org/support" +        } +      ], +      "dependencies": { +        "base64-js": "^1.3.1", +        "ieee754": "^1.1.13" +      } +    },      "node_modules/bytes": {        "version": "3.1.0",        "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.1.0.tgz", @@ -625,6 +698,14 @@          "node": ">=0.4.0"        }      }, +    "node_modules/denque": { +      "version": "2.0.1", +      "resolved": "https://registry.npmjs.org/denque/-/denque-2.0.1.tgz", +      "integrity": "sha512-tfiWc6BQLXNLpNiR5iGd0Ocu3P3VpxfzFiqubLgMfhfOw9WyvgJBd46CClNn9k3qfbjvT//0cf7AlYRX/OslMQ==", +      "engines": { +        "node": ">=0.10" +      } +    },      "node_modules/depd": {        "version": "1.1.2",        "resolved": "https://registry.npmjs.org/depd/-/depd-1.1.2.tgz", @@ -1579,6 +1660,25 @@          "node": ">=0.10.0"        }      }, +    "node_modules/ieee754": { +      "version": "1.2.1", +      "resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.2.1.tgz", +      "integrity": "sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA==", +      "funding": [ +        { +          "type": "github", +          "url": "https://github.com/sponsors/feross" +        }, +        { +          "type": "patreon", +          "url": "https://www.patreon.com/feross" +        }, +        { +          "type": "consulting", +          "url": "https://feross.org/support" +        } +      ] +    },      "node_modules/ignore": {        "version": "4.0.6",        "resolved": "https://registry.npmjs.org/ignore/-/ignore-4.0.6.tgz", @@ -1628,6 +1728,11 @@        "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz",        "integrity": "sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4="      }, +    "node_modules/ip": { +      "version": "1.1.5", +      "resolved": "https://registry.npmjs.org/ip/-/ip-1.1.5.tgz", +      "integrity": "sha1-vd7XARQpCCjAoDnnLvJfWq7ENUo=" +    },      "node_modules/ipaddr.js": {        "version": "1.9.1",        "resolved": "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-1.9.1.tgz", @@ -1840,6 +1945,11 @@          "promise": "^7.0.1"        }      }, +    "node_modules/kareem": { +      "version": "2.3.4", +      "resolved": "https://registry.npmjs.org/kareem/-/kareem-2.3.4.tgz", +      "integrity": "sha512-Vcrt8lcpVl0s8ePx634BxwRqmFo+5DcOhlmNadehxreMTIQi/9hOL/B3hZQQbK5DgMS7Lem3xABXV7/S3jy+7g==" +    },      "node_modules/katex": {        "version": "0.11.1",        "resolved": "https://registry.npmjs.org/katex/-/katex-0.11.1.tgz", @@ -1987,6 +2097,12 @@          "url": "https://github.com/sindresorhus/mem?sponsor=1"        }      }, +    "node_modules/memory-pager": { +      "version": "1.5.0", +      "resolved": "https://registry.npmjs.org/memory-pager/-/memory-pager-1.5.0.tgz", +      "integrity": "sha512-ZS4Bp4r/Zoeq6+NLJpP+0Zzm0pR8whtGPf1XExKLJBAczGMnSi3It14OiNCStjQjM6NU1okjQGSxgEZN8eBYKg==", +      "optional": true +    },      "node_modules/merge-descriptors": {        "version": "1.0.1",        "resolved": "https://registry.npmjs.org/merge-descriptors/-/merge-descriptors-1.0.1.tgz", @@ -2054,6 +2170,89 @@          "node": "*"        }      }, +    "node_modules/mongodb": { +      "version": "4.3.1", +      "resolved": "https://registry.npmjs.org/mongodb/-/mongodb-4.3.1.tgz", +      "integrity": "sha512-sNa8APSIk+r4x31ZwctKjuPSaeKuvUeNb/fu/3B6dRM02HpEgig7hTHM8A/PJQTlxuC/KFWlDlQjhsk/S43tBg==", +      "dependencies": { +        "bson": "^4.6.1", +        "denque": "^2.0.1", +        "mongodb-connection-string-url": "^2.4.1", +        "socks": "^2.6.1" +      }, +      "engines": { +        "node": ">=12.9.0" +      }, +      "optionalDependencies": { +        "saslprep": "^1.0.3" +      } +    }, +    "node_modules/mongodb-connection-string-url": { +      "version": "2.5.2", +      "resolved": "https://registry.npmjs.org/mongodb-connection-string-url/-/mongodb-connection-string-url-2.5.2.tgz", +      "integrity": "sha512-tWDyIG8cQlI5k3skB6ywaEA5F9f5OntrKKsT/Lteub2zgwSUlhqEN2inGgBTm8bpYJf8QYBdA/5naz65XDpczA==", +      "dependencies": { +        "@types/whatwg-url": "^8.2.1", +        "whatwg-url": "^11.0.0" +      } +    }, +    "node_modules/mongodb-connection-string-url/node_modules/tr46": { +      "version": "3.0.0", +      "resolved": "https://registry.npmjs.org/tr46/-/tr46-3.0.0.tgz", +      "integrity": "sha512-l7FvfAHlcmulp8kr+flpQZmVwtu7nfRV7NZujtN0OqES8EL4O4e0qqzL0DC5gAvx/ZC/9lk6rhcUwYvkBnBnYA==", +      "dependencies": { +        "punycode": "^2.1.1" +      }, +      "engines": { +        "node": ">=12" +      } +    }, +    "node_modules/mongodb-connection-string-url/node_modules/webidl-conversions": { +      "version": "7.0.0", +      "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-7.0.0.tgz", +      "integrity": "sha512-VwddBukDzu71offAQR975unBIGqfKZpM+8ZX6ySk8nYhVoo5CYaZyzt3YBvYtRtO+aoGlqxPg/B87NGVZ/fu6g==", +      "engines": { +        "node": ">=12" +      } +    }, +    "node_modules/mongodb-connection-string-url/node_modules/whatwg-url": { +      "version": "11.0.0", +      "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-11.0.0.tgz", +      "integrity": "sha512-RKT8HExMpoYx4igMiVMY83lN6UeITKJlBQ+vR/8ZJ8OCdSiN3RwCq+9gH0+Xzj0+5IrM6i4j/6LuvzbZIQgEcQ==", +      "dependencies": { +        "tr46": "^3.0.0", +        "webidl-conversions": "^7.0.0" +      }, +      "engines": { +        "node": ">=12" +      } +    }, +    "node_modules/mongoose": { +      "version": "6.2.8", +      "resolved": "https://registry.npmjs.org/mongoose/-/mongoose-6.2.8.tgz", +      "integrity": "sha512-Wq6HG0sOJEQHp5YqMlxrnf93vBFwdY2zlAwqI97EPPSt69kiVV21pTv4cDanrCNWi4upG8ajQ/p9jpDjcECjkQ==", +      "dependencies": { +        "bson": "^4.2.2", +        "kareem": "2.3.4", +        "mongodb": "4.3.1", +        "mpath": "0.8.4", +        "mquery": "4.0.2", +        "ms": "2.1.3", +        "sift": "16.0.0" +      }, +      "engines": { +        "node": ">=12.0.0" +      }, +      "funding": { +        "type": "opencollective", +        "url": "https://opencollective.com/mongoose" +      } +    }, +    "node_modules/mongoose/node_modules/ms": { +      "version": "2.1.3", +      "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", +      "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==" +    },      "node_modules/morgan": {        "version": "1.10.0",        "resolved": "https://registry.npmjs.org/morgan/-/morgan-1.10.0.tgz", @@ -2077,6 +2276,46 @@          "node": ">= 0.8"        }      }, +    "node_modules/mpath": { +      "version": "0.8.4", +      "resolved": "https://registry.npmjs.org/mpath/-/mpath-0.8.4.tgz", +      "integrity": "sha512-DTxNZomBcTWlrMW76jy1wvV37X/cNNxPW1y2Jzd4DZkAaC5ZGsm8bfGfNOthcDuRJujXLqiuS6o3Tpy0JEoh7g==", +      "engines": { +        "node": ">=4.0.0" +      } +    }, +    "node_modules/mquery": { +      "version": "4.0.2", +      "resolved": "https://registry.npmjs.org/mquery/-/mquery-4.0.2.tgz", +      "integrity": "sha512-oAVF0Nil1mT3rxty6Zln4YiD6x6QsUWYz927jZzjMxOK2aqmhEz5JQ7xmrKK7xRFA2dwV+YaOpKU/S+vfNqKxA==", +      "dependencies": { +        "debug": "4.x" +      }, +      "engines": { +        "node": ">=12.0.0" +      } +    }, +    "node_modules/mquery/node_modules/debug": { +      "version": "4.3.4", +      "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", +      "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==", +      "dependencies": { +        "ms": "2.1.2" +      }, +      "engines": { +        "node": ">=6.0" +      }, +      "peerDependenciesMeta": { +        "supports-color": { +          "optional": true +        } +      } +    }, +    "node_modules/mquery/node_modules/ms": { +      "version": "2.1.2", +      "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", +      "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==" +    },      "node_modules/ms": {        "version": "2.0.0",        "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", @@ -2515,6 +2754,18 @@        "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz",        "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg=="      }, +    "node_modules/saslprep": { +      "version": "1.0.3", +      "resolved": "https://registry.npmjs.org/saslprep/-/saslprep-1.0.3.tgz", +      "integrity": "sha512-/MY/PEMbk2SuY5sScONwhUDsV2p77Znkb/q3nSVstq/yQzYJOH/Azh29p9oJLsl3LnQwSvZDKagDGBsBwSooag==", +      "optional": true, +      "dependencies": { +        "sparse-bitfield": "^3.0.3" +      }, +      "engines": { +        "node": ">=6" +      } +    },      "node_modules/saxes": {        "version": "5.0.1",        "resolved": "https://registry.npmjs.org/saxes/-/saxes-5.0.1.tgz", @@ -2622,6 +2873,11 @@          "node": ">=8"        }      }, +    "node_modules/sift": { +      "version": "16.0.0", +      "resolved": "https://registry.npmjs.org/sift/-/sift-16.0.0.tgz", +      "integrity": "sha512-ILTjdP2Mv9V1kIxWMXeMTIRbOBrqKc4JAXmFMnFq3fKeyQ2Qwa3Dw1ubcye3vR+Y6ofA0b9gNDr/y2t6eUeIzQ==" +    },      "node_modules/slice-ansi": {        "version": "4.0.0",        "resolved": "https://registry.npmjs.org/slice-ansi/-/slice-ansi-4.0.0.tgz", @@ -2672,6 +2928,28 @@        "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==",        "dev": true      }, +    "node_modules/smart-buffer": { +      "version": "4.2.0", +      "resolved": "https://registry.npmjs.org/smart-buffer/-/smart-buffer-4.2.0.tgz", +      "integrity": "sha512-94hK0Hh8rPqQl2xXc3HsaBoOXKV20MToPkcXvwbISWLEs+64sBq5kFgn2kJDHb1Pry9yrP0dxrCI9RRci7RXKg==", +      "engines": { +        "node": ">= 6.0.0", +        "npm": ">= 3.0.0" +      } +    }, +    "node_modules/socks": { +      "version": "2.6.2", +      "resolved": "https://registry.npmjs.org/socks/-/socks-2.6.2.tgz", +      "integrity": "sha512-zDZhHhZRY9PxRruRMR7kMhnf3I8hDs4S3f9RecfnGxvcBHQcKcIH/oUcEWffsfl1XxdYlA7nnlGbbTvPz9D8gA==", +      "dependencies": { +        "ip": "^1.1.5", +        "smart-buffer": "^4.2.0" +      }, +      "engines": { +        "node": ">= 10.13.0", +        "npm": ">= 3.0.0" +      } +    },      "node_modules/source-map": {        "version": "0.6.1",        "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", @@ -2681,6 +2959,15 @@          "node": ">=0.10.0"        }      }, +    "node_modules/sparse-bitfield": { +      "version": "3.0.3", +      "resolved": "https://registry.npmjs.org/sparse-bitfield/-/sparse-bitfield-3.0.3.tgz", +      "integrity": "sha1-/0rm5oZWBWuks+eSqzM004JzyhE=", +      "optional": true, +      "dependencies": { +        "memory-pager": "^1.0.2" +      } +    },      "node_modules/spdy": {        "version": "4.0.2",        "resolved": "https://registry.npmjs.org/spdy/-/spdy-4.0.2.tgz", @@ -3297,6 +3584,25 @@        "resolved": "https://registry.npmjs.org/@tootallnate/once/-/once-1.1.2.tgz",        "integrity": "sha512-RbzJvlNzmRq5c3O09UipeuXno4tA1FE6ikOjxZK0tuxVv3412l64l5t1W5pj4+rJq9vpkm/kwiR07aZXnsKPxw=="      }, +    "@types/node": { +      "version": "17.0.23", +      "resolved": "https://registry.npmjs.org/@types/node/-/node-17.0.23.tgz", +      "integrity": "sha512-UxDxWn7dl97rKVeVS61vErvw086aCYhDLyvRQZ5Rk65rZKepaFdm53GeqXaKBuOhED4e9uWq34IC3TdSdJJ2Gw==" +    }, +    "@types/webidl-conversions": { +      "version": "6.1.1", +      "resolved": "https://registry.npmjs.org/@types/webidl-conversions/-/webidl-conversions-6.1.1.tgz", +      "integrity": "sha512-XAahCdThVuCFDQLT7R7Pk/vqeObFNL3YqRyFZg+AqAP/W1/w3xHaIxuW7WszQqTbIBOPRcItYJIou3i/mppu3Q==" +    }, +    "@types/whatwg-url": { +      "version": "8.2.1", +      "resolved": "https://registry.npmjs.org/@types/whatwg-url/-/whatwg-url-8.2.1.tgz", +      "integrity": "sha512-2YubE1sjj5ifxievI5Ge1sckb9k/Er66HyR2c+3+I6VDUUg1TLPdYYTEbQ+DjRkS4nTxMJhgWfSfMRD2sl2EYQ==", +      "requires": { +        "@types/node": "*", +        "@types/webidl-conversions": "*" +      } +    },      "abab": {        "version": "2.0.5",        "resolved": "https://registry.npmjs.org/abab/-/abab-2.0.5.tgz", @@ -3451,6 +3757,11 @@        "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz",        "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw=="      }, +    "base64-js": { +      "version": "1.5.1", +      "resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.5.1.tgz", +      "integrity": "sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==" +    },      "basic-auth": {        "version": "2.0.1",        "resolved": "https://registry.npmjs.org/basic-auth/-/basic-auth-2.0.1.tgz", @@ -3490,6 +3801,23 @@        "resolved": "https://registry.npmjs.org/browser-process-hrtime/-/browser-process-hrtime-1.0.0.tgz",        "integrity": "sha512-9o5UecI3GhkpM6DrXr69PblIuWxPKk9Y0jHBRhdocZ2y7YECBFCsHm79Pr3OyR2AvjhDkabFJaDJMYRazHgsow=="      }, +    "bson": { +      "version": "4.6.2", +      "resolved": "https://registry.npmjs.org/bson/-/bson-4.6.2.tgz", +      "integrity": "sha512-VeJKHShcu1b/ugl0QiujlVuBepab714X9nNyBdA1kfekuDGecxgpTA2Z6nYbagrWFeiIyzSWIOzju3lhj+RNyQ==", +      "requires": { +        "buffer": "^5.6.0" +      } +    }, +    "buffer": { +      "version": "5.7.1", +      "resolved": "https://registry.npmjs.org/buffer/-/buffer-5.7.1.tgz", +      "integrity": "sha512-EHcyIPBQ4BSGlvjB16k5KgAJ27CIsHY/2JBmCRReo48y9rQ3MaUzWX3KVlBa4U7MyX02HdVj0K7C3WaB3ju7FQ==", +      "requires": { +        "base64-js": "^1.3.1", +        "ieee754": "^1.1.13" +      } +    },      "bytes": {        "version": "3.1.0",        "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.1.0.tgz", @@ -3660,6 +3988,11 @@        "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz",        "integrity": "sha1-3zrhmayt+31ECqrgsp4icrJOxhk="      }, +    "denque": { +      "version": "2.0.1", +      "resolved": "https://registry.npmjs.org/denque/-/denque-2.0.1.tgz", +      "integrity": "sha512-tfiWc6BQLXNLpNiR5iGd0Ocu3P3VpxfzFiqubLgMfhfOw9WyvgJBd46CClNn9k3qfbjvT//0cf7AlYRX/OslMQ==" +    },      "depd": {        "version": "1.1.2",        "resolved": "https://registry.npmjs.org/depd/-/depd-1.1.2.tgz", @@ -4375,6 +4708,11 @@          "safer-buffer": ">= 2.1.2 < 3"        }      }, +    "ieee754": { +      "version": "1.2.1", +      "resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.2.1.tgz", +      "integrity": "sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA==" +    },      "ignore": {        "version": "4.0.6",        "resolved": "https://registry.npmjs.org/ignore/-/ignore-4.0.6.tgz", @@ -4412,6 +4750,11 @@        "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz",        "integrity": "sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4="      }, +    "ip": { +      "version": "1.1.5", +      "resolved": "https://registry.npmjs.org/ip/-/ip-1.1.5.tgz", +      "integrity": "sha1-vd7XARQpCCjAoDnnLvJfWq7ENUo=" +    },      "ipaddr.js": {        "version": "1.9.1",        "resolved": "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-1.9.1.tgz", @@ -4579,6 +4922,11 @@          "promise": "^7.0.1"        }      }, +    "kareem": { +      "version": "2.3.4", +      "resolved": "https://registry.npmjs.org/kareem/-/kareem-2.3.4.tgz", +      "integrity": "sha512-Vcrt8lcpVl0s8ePx634BxwRqmFo+5DcOhlmNadehxreMTIQi/9hOL/B3hZQQbK5DgMS7Lem3xABXV7/S3jy+7g==" +    },      "katex": {        "version": "0.11.1",        "resolved": "https://registry.npmjs.org/katex/-/katex-0.11.1.tgz", @@ -4702,6 +5050,12 @@          "mimic-fn": "^3.0.0"        }      }, +    "memory-pager": { +      "version": "1.5.0", +      "resolved": "https://registry.npmjs.org/memory-pager/-/memory-pager-1.5.0.tgz", +      "integrity": "sha512-ZS4Bp4r/Zoeq6+NLJpP+0Zzm0pR8whtGPf1XExKLJBAczGMnSi3It14OiNCStjQjM6NU1okjQGSxgEZN8eBYKg==", +      "optional": true +    },      "merge-descriptors": {        "version": "1.0.1",        "resolved": "https://registry.npmjs.org/merge-descriptors/-/merge-descriptors-1.0.1.tgz", @@ -4748,6 +5102,72 @@          "brace-expansion": "^1.1.7"        }      }, +    "mongodb": { +      "version": "4.3.1", +      "resolved": "https://registry.npmjs.org/mongodb/-/mongodb-4.3.1.tgz", +      "integrity": "sha512-sNa8APSIk+r4x31ZwctKjuPSaeKuvUeNb/fu/3B6dRM02HpEgig7hTHM8A/PJQTlxuC/KFWlDlQjhsk/S43tBg==", +      "requires": { +        "bson": "^4.6.1", +        "denque": "^2.0.1", +        "mongodb-connection-string-url": "^2.4.1", +        "saslprep": "^1.0.3", +        "socks": "^2.6.1" +      } +    }, +    "mongodb-connection-string-url": { +      "version": "2.5.2", +      "resolved": "https://registry.npmjs.org/mongodb-connection-string-url/-/mongodb-connection-string-url-2.5.2.tgz", +      "integrity": "sha512-tWDyIG8cQlI5k3skB6ywaEA5F9f5OntrKKsT/Lteub2zgwSUlhqEN2inGgBTm8bpYJf8QYBdA/5naz65XDpczA==", +      "requires": { +        "@types/whatwg-url": "^8.2.1", +        "whatwg-url": "^11.0.0" +      }, +      "dependencies": { +        "tr46": { +          "version": "3.0.0", +          "resolved": "https://registry.npmjs.org/tr46/-/tr46-3.0.0.tgz", +          "integrity": "sha512-l7FvfAHlcmulp8kr+flpQZmVwtu7nfRV7NZujtN0OqES8EL4O4e0qqzL0DC5gAvx/ZC/9lk6rhcUwYvkBnBnYA==", +          "requires": { +            "punycode": "^2.1.1" +          } +        }, +        "webidl-conversions": { +          "version": "7.0.0", +          "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-7.0.0.tgz", +          "integrity": "sha512-VwddBukDzu71offAQR975unBIGqfKZpM+8ZX6ySk8nYhVoo5CYaZyzt3YBvYtRtO+aoGlqxPg/B87NGVZ/fu6g==" +        }, +        "whatwg-url": { +          "version": "11.0.0", +          "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-11.0.0.tgz", +          "integrity": "sha512-RKT8HExMpoYx4igMiVMY83lN6UeITKJlBQ+vR/8ZJ8OCdSiN3RwCq+9gH0+Xzj0+5IrM6i4j/6LuvzbZIQgEcQ==", +          "requires": { +            "tr46": "^3.0.0", +            "webidl-conversions": "^7.0.0" +          } +        } +      } +    }, +    "mongoose": { +      "version": "6.2.8", +      "resolved": "https://registry.npmjs.org/mongoose/-/mongoose-6.2.8.tgz", +      "integrity": "sha512-Wq6HG0sOJEQHp5YqMlxrnf93vBFwdY2zlAwqI97EPPSt69kiVV21pTv4cDanrCNWi4upG8ajQ/p9jpDjcECjkQ==", +      "requires": { +        "bson": "^4.2.2", +        "kareem": "2.3.4", +        "mongodb": "4.3.1", +        "mpath": "0.8.4", +        "mquery": "4.0.2", +        "ms": "2.1.3", +        "sift": "16.0.0" +      }, +      "dependencies": { +        "ms": { +          "version": "2.1.3", +          "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", +          "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==" +        } +      } +    },      "morgan": {        "version": "1.10.0",        "resolved": "https://registry.npmjs.org/morgan/-/morgan-1.10.0.tgz", @@ -4767,6 +5187,34 @@          }        }      }, +    "mpath": { +      "version": "0.8.4", +      "resolved": "https://registry.npmjs.org/mpath/-/mpath-0.8.4.tgz", +      "integrity": "sha512-DTxNZomBcTWlrMW76jy1wvV37X/cNNxPW1y2Jzd4DZkAaC5ZGsm8bfGfNOthcDuRJujXLqiuS6o3Tpy0JEoh7g==" +    }, +    "mquery": { +      "version": "4.0.2", +      "resolved": "https://registry.npmjs.org/mquery/-/mquery-4.0.2.tgz", +      "integrity": "sha512-oAVF0Nil1mT3rxty6Zln4YiD6x6QsUWYz927jZzjMxOK2aqmhEz5JQ7xmrKK7xRFA2dwV+YaOpKU/S+vfNqKxA==", +      "requires": { +        "debug": "4.x" +      }, +      "dependencies": { +        "debug": { +          "version": "4.3.4", +          "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", +          "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==", +          "requires": { +            "ms": "2.1.2" +          } +        }, +        "ms": { +          "version": "2.1.2", +          "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", +          "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==" +        } +      } +    },      "ms": {        "version": "2.0.0",        "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", @@ -5121,6 +5569,15 @@        "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz",        "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg=="      }, +    "saslprep": { +      "version": "1.0.3", +      "resolved": "https://registry.npmjs.org/saslprep/-/saslprep-1.0.3.tgz", +      "integrity": "sha512-/MY/PEMbk2SuY5sScONwhUDsV2p77Znkb/q3nSVstq/yQzYJOH/Azh29p9oJLsl3LnQwSvZDKagDGBsBwSooag==", +      "optional": true, +      "requires": { +        "sparse-bitfield": "^3.0.3" +      } +    },      "saxes": {        "version": "5.0.1",        "resolved": "https://registry.npmjs.org/saxes/-/saxes-5.0.1.tgz", @@ -5206,6 +5663,11 @@        "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==",        "dev": true      }, +    "sift": { +      "version": "16.0.0", +      "resolved": "https://registry.npmjs.org/sift/-/sift-16.0.0.tgz", +      "integrity": "sha512-ILTjdP2Mv9V1kIxWMXeMTIRbOBrqKc4JAXmFMnFq3fKeyQ2Qwa3Dw1ubcye3vR+Y6ofA0b9gNDr/y2t6eUeIzQ==" +    },      "slice-ansi": {        "version": "4.0.0",        "resolved": "https://registry.npmjs.org/slice-ansi/-/slice-ansi-4.0.0.tgz", @@ -5243,12 +5705,35 @@          }        }      }, +    "smart-buffer": { +      "version": "4.2.0", +      "resolved": "https://registry.npmjs.org/smart-buffer/-/smart-buffer-4.2.0.tgz", +      "integrity": "sha512-94hK0Hh8rPqQl2xXc3HsaBoOXKV20MToPkcXvwbISWLEs+64sBq5kFgn2kJDHb1Pry9yrP0dxrCI9RRci7RXKg==" +    }, +    "socks": { +      "version": "2.6.2", +      "resolved": "https://registry.npmjs.org/socks/-/socks-2.6.2.tgz", +      "integrity": "sha512-zDZhHhZRY9PxRruRMR7kMhnf3I8hDs4S3f9RecfnGxvcBHQcKcIH/oUcEWffsfl1XxdYlA7nnlGbbTvPz9D8gA==", +      "requires": { +        "ip": "^1.1.5", +        "smart-buffer": "^4.2.0" +      } +    },      "source-map": {        "version": "0.6.1",        "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz",        "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==",        "optional": true      }, +    "sparse-bitfield": { +      "version": "3.0.3", +      "resolved": "https://registry.npmjs.org/sparse-bitfield/-/sparse-bitfield-3.0.3.tgz", +      "integrity": "sha1-/0rm5oZWBWuks+eSqzM004JzyhE=", +      "optional": true, +      "requires": { +        "memory-pager": "^1.0.2" +      } +    },      "spdy": {        "version": "4.0.2",        "resolved": "https://registry.npmjs.org/spdy/-/spdy-4.0.2.tgz", diff --git a/package.json b/package.json index e7d7a5e..bef37be 100644 --- a/package.json +++ b/package.json @@ -28,6 +28,7 @@      "markdown-it-highlightjs": "^3.4.0",      "markdown-it-multimd-table": "^4.0.2",      "markdown-it-texmath": "^0.7.0", +    "mongoose": "^6.2.8",      "morgan": "^1.10.0",      "pug": "^3.0.2",      "spdy": "^4.0.2" diff --git a/put_in_db.js b/put_in_db.js new file mode 100644 index 0000000..da5a050 --- /dev/null +++ b/put_in_db.js @@ -0,0 +1,26 @@ +"use strict"; +// mongosh --host 127.0.0.1 --port 27117 -u mongo -p mongo -f put_in_db.js + +const fs = require("fs"); +const path = require("path"); +// db = connect("http://mongo:mongo@127.0.0.1:27117"); + +blog_entry_1 = { +  title: "Turning C structs into Lua tables", +  slug: "c_struct_lua_table", +  body: fs.readFileSync(path.join(__dirname) + "/mds/cstruct2luatable.md"), +  teaser: "Turning C structures into Lua tables", +  keywords: "c,lua", +  lastUpdatedAt: Date.now(), +}; + +blog_entry_2 = { +  title: "Lazy Makefiles", +  slug: "lazy_makefile", +  body: fs.readFileSync(path.join(__dirname) + "/mds/lazymakefiles.md"), +  teaser: "Lazy Makefiles", +  keywords: "makefile,c,c++", +  lastUpdatedAt: Date.now(), +}; + +db.blogposts.insertMany([blog_entry_1, blog_entry_2]); @@ -22,42 +22,80 @@ const mit = require("markdown-it")({ html: true })  const spdy = require("spdy");  const helmet = require("helmet");  const morgan = require("morgan"); -const pug = require("pug"); +const model = require("./model"); + +model.dbInit();  const app = express(); +app.disable("x-powered-by");  app.use(express.static(path.join(__dirname, "css")));  app.use(express.static(path.join(__dirname, "static")));  app.set("views", path.join(__dirname, "views"));  app.set("view engine", "ejs"); -app.engine("ejs", require("ejs").__express); -app.use(helmet()); +app.set("view engine", "pug"); + +app.use(helmet.crossOriginEmbedderPolicy()); +app.use(helmet.crossOriginOpenerPolicy()); +app.use(helmet.crossOriginResourcePolicy()); +app.use(helmet.dnsPrefetchControl()); +app.use(helmet.expectCt()); +app.use(helmet.frameguard()); +app.use(helmet.hidePoweredBy()); +app.use(helmet.hsts()); +app.use(helmet.ieNoOpen()); +app.use(helmet.noSniff()); +app.use(helmet.originAgentCluster()); +app.use(helmet.permittedCrossDomainPolicies()); +app.use(helmet.referrerPolicy()); +app.use(helmet.xssFilter()); +app.use((req, res, next) => { +  res.setHeader( +    "Permissions-Policy", +    "geolocation=(self),midi=(self),sync-xhr=(self),microphone=(self),camera=(self),magnetometer=(self),gyroscope=(self),fullscreen=(self),payment=(self),usb=(self)" +  ); +  next(); +}); +app.use( +  helmet.contentSecurityPolicy({ +    useDefaults: false, +    directives: { +      baseUri: ["self"], +      defaultSrc: ["self"], +      scriptSrc: ["none"], +      styleSrc: ["self", "https:", "unsafef-inline"], +    }, +  }) +); +  app.use(morgan("combined")); -function renderAndSend(req, res) { -  try { -    let viewPath; -    if (req.path == "/") { -      viewPath = "mds/cstruct2luatable.md"; -    } else { -      viewPath = req.path; -    } -    let readStream = fs.createReadStream( -      path.join(__dirname, viewPath), -      "utf-8" -    ); -    //FIXME-this can obviously fail -    readStream.on("data", (chunk) => { -      res.render("index", { +async function enumerateDir() { +  return await fs.readdirSync(path.join(__dirname, "mds")); +} + +function renderAndSend_v2(req, res, slug) { +  model.blogPost +    .findOne( +      { slug: slug }, +      { +        projection: { +          _id: 0, +          title: 0, +          teaser: 0, +        }, +      } +    ) +    .exec(function (err, blogPost) { +      if (err) return err; +      return res.render("index.ejs", {          cache: true,          data: { -          blogHttp: mit.render(chunk), -          mds: fs.readdirSync(path.join(__dirname, "mds"), "utf-8"), +          blogHttp: mit.render(blogPost.body), +          lastUpdatedAt: blogPost.lastUpdatedAt, +          keywords: blogPost.keywords,          },        });      }); -  } catch (err) { -    console.log(err); -  }  }  app.get("/health", (req, res) => { @@ -73,12 +111,17 @@ app.get("/about", (req, res) => {  app.get("/archive", (req, res) => {    res.type("text/html"); -  res.render("archive", { -    cache: true, -    data: { -      mds: fs.readdirSync(path.join(__dirname, "mds"), "utf-8"), -    }, -  }); +  model.blogPost +    .find({}, { _id: 0, body: 0, teaser: 0, keywords: 0, lastUpdatedAt: 0 }) +    .exec(function (err, blogPosts) { +      if (err) return err; +      res.render("archive.ejs", { +        cache: true, +        data: { +          blogPosts: blogPosts, +        }, +      }); +    });  });  app.get("/robots.txt", (req, res) => { @@ -90,25 +133,42 @@ app.get("/robots.txt", (req, res) => {    res.send(robots_txt);  }); -// app.get("/rss/feed", (req, res) => { -//   let html = pug.renderFile("./views/rss_feed.pug", merge(options, localls)); -//   res.send(html); -// }); - -app.get("/$", (req, res) => { -  renderAndSend(req, res); +app.get("/rss/feed", (req, res) => { +  res.type("application/rss+xml"); +  model.blogPost +    .find({}) +    .sort("-lastUpdatedAt") +    .select("title slug lastUpdatedAt teaser") +    .exec(function (err, posts) { +      if (err) return err; +      return res.render("rss_feed_v2.pug", { cache: true, posts: posts }); +    });  }); -app.get("/mds/:mdname$", (req, res) => { -  if (req.params["mdname"] == "") { +app.get("/posts/:postName", (req, res) => { +  if (req.params["postName"] == "") {      res.write("nothing requested!");    } -  renderAndSend(req, res); +  renderAndSend_v2(req, res, req.params.postName);  }); -async function enumerateDir() { -  return await fs.readdirSync(path.join(__dirname, "mds")); -} +app.get("/$", (req, res) => { +  model.blogPost +    .find({}, { projection: { _id: 0, title: 0, teaser: 0 } }) +    .limit(1) +    .sort({ $natural: -1 }) +    .exec(function (err, blogPost) { +      if (err) return err; +      return res.render("index.ejs", { +        cache: true, +        data: { +          blogHttp: mit.render(blogPost[0].body), +          lastUpdatedAt: blogPost[0].lastUpdatedAt, +          keywords: blogPost[0].keywords, +        }, +      }); +    }); +});  app.use(sitemap(enumerateDir, "https://blog.terminaldweller.com")); diff --git a/static/about.html b/static/about.html index ad9ed10..a56ad24 100644 --- a/static/about.html +++ b/static/about.html @@ -18,6 +18,18 @@      <p>        You can find my github        <a href="https://github.com/terminaldweller">here</a> +      .      </p> +    <p> +      Also if the blog is broken please make a new issue +      <a href="https://github.com/terminaldweller/web">here</a> +      . +    </p> +    <br /> +    <br /> +    <hr /> +    <br /> +    <a href="/" class="left-footer">Home</a> +    <br />    </body>  </html> diff --git a/views/archive.ejs b/views/archive.ejs index 36191de..72b963d 100644 --- a/views/archive.ejs +++ b/views/archive.ejs @@ -9,9 +9,9 @@    <body>      <script>0</script>      <div class="article"> -      <% data.mds.forEach(function(md) { %> +      <% data.blogPosts.forEach(function(blogPost) { %>          <ul> -          <li><a href=<%= "/mds/"+md %> target="_self" rel="noreferrer noopener" type="text/html"><%= md %></a></li> +          <li><a href=<%= "/posts/"+blogPost.slug %> target="_self" rel="noreferrer noopener" type="text/html"><%= blogPost.title %></a></li>          </ul>        <% }) %>      </div> diff --git a/views/index.ejs b/views/index.ejs index 4679e4a..fdd49cc 100644 --- a/views/index.ejs +++ b/views/index.ejs @@ -5,16 +5,27 @@      <meta name="viewport" content="width=device-width">      <title>Blog</title>      <link rel="stylesheet" href="/master.css" type="text/css" media="screen" title="no title" charset="utf-8"> +    <link rel="alternate" type="application/rss+xml" title="RSS" href="/rss/feed"> +    <!-- <link rel="alternate" type="application/atom+xml" title="RSS" href="/feed/rss"> -->    </head>    <body> -    <script>0</script> +    <!-- <script>0</script> -->      <div class="article">      <%- data.blogHttp %>      <br/>      <hr/>      <br/> +    <a class="left-footer">Keywords:</a> +    <%- data.keywords %> +    <%- data.lastUpdated %> +    <br/> +    <br/> +    <hr/> +    <br/>      <a href="/archive" class="left-footer">Archive</a>      <a href="/about" class="right-footer">About</a> +    <a class="right-footer">   </a> +    <a href="/rss/feed" class="right-footer">RSS</a>      </div>    </body>  </html> diff --git a/views/rss_feed.pug b/views/rss_feed.pug new file mode 100644 index 0000000..e75225d --- /dev/null +++ b/views/rss_feed.pug @@ -0,0 +1,21 @@ +doctype xml +rss(version='2.0', xmlns:atom='<a href="http://www.w3.org/2005/Atom" rel="nofollow">http://www.w3.org/2005/Atom</a>') +    channel +        title deviblog +        link <a href="https://blog.terminaldweller.com" rel="nofollow">https://blog.terminaldweller.com</a> +        atom:link(href='<a href="https://blog.terminaldweller.com/feed/rss" rel="nofollow">https://blog.terminaldweller.com/feed/rss</a>', rel='self', type='application/rss+xml') +        description I talk about software here. +        language en-US +        if posts.length +            lastBuildDate= new Date(posts[0].lastUpdatedAt).toUTCString() +        each post in posts +            item +                title= post.title +                link <a href="https://blog.terminaldweller.com/blog/#{post.slug}" rel="nofollow">https://terminaldweller.com/blog/#{post.slug}</a> +                description +                    | <![CDATA[ +                    | !{post.teaser} +                    p: a(href='<a href="https://blog.terminaldweller.com/blog/#{post.slug} rel="nofollow">https://blog.terminaldweller.com/blog/#{post.slug}</a>') 'Read more »' +                    | ]]> +                pubDate= new Date(post.lastUpdatedAt).toUTCString() +                guid(isPermaLink='false') <a href="https://blog.terminaldweller.com/blog/#{post.slug}" rel="nofollow">https://blog.terminaldweller.com/blog/#{post.slug}</a> diff --git a/views/rss_feed_v2.pug b/views/rss_feed_v2.pug new file mode 100644 index 0000000..d04297d --- /dev/null +++ b/views/rss_feed_v2.pug @@ -0,0 +1,22 @@ +doctype xml +rss(version='2.0', xmlns:atom='http://www.w3.org/2005/Atom') +    channel +        title deviblog +        link https://blog.terminaldweller.com +        atom:link(href='https://blog.terminaldweller.com/rss/feed', rel='self', type='application/rss+xml') +        description I talk about software here. +        managingEditor devi@terminaldweller.com (Farzad Sadeghi) +        webMaster devi@terminaldweller.com (Farzad Sadeghi) +        language en-US +        if posts.length +            lastBuildDate= new Date(posts[0].lastUpdatedAt).toUTCString() +        each post in posts +            item +                title= post.title +                link https://blog.terminaldweller.com/posts/#{post.slug} +                description +                    | <![CDATA[ +                    | #{post.teaser} +                    | ]]> +                pubDate= new Date(post.lastUpdatedAt).toUTCString() +                guid(isPermaLink='false') https://blog.terminaldweller.com/blog/#{post.slug} | 
