@tenjuu99/blog 0.1.4 → 0.1.7

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/LICENSE ADDED
@@ -0,0 +1,7 @@
1
+ Copyright 2024 Amashige Seiji
2
+
3
+ Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the “Software”), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
4
+
5
+ The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
6
+
7
+ THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
package/README.md CHANGED
@@ -1,21 +1,18 @@
1
1
  # blog template
2
2
 
3
- ## プレビュー
4
-
5
- 以下のコマンドでプレビューできます。
3
+ ## setup
6
4
 
7
5
  ```
8
- npm run watch
6
+ npm i @tenjuu99/blog
9
7
  ```
10
8
 
11
- `http://localhost:8000/`
12
-
13
- デフォルトでは8000ポートを利用しますが、環境変数を使ってポート番号を上書きできます。
14
-
15
9
  ```
16
- PORT=8001 npm run watch
10
+ npx create-blog
11
+ npx server
17
12
  ```
18
13
 
14
+ `http://localhost:8000` にアクセスできます
15
+
19
16
  ## 記事を書く
20
17
 
21
18
  `./data/` 以下にマークダウンファイルを入稿します。
@@ -122,24 +119,7 @@ This is else content.
122
119
  ### SCRIPT
123
120
 
124
121
  ```markdown
125
- {script}
126
- // write javascript and return value
127
- {/script}
122
+ <script type="ssg">
123
+ return 'これはスクリプトが実行された結果出力されました。'
124
+ </script>
128
125
  ```
129
-
130
- ## デプロイ
131
-
132
- AWS S3 にデプロイするには、 `.github/workflow/deploy.yml.sample` を `.github/workflow/deploy.yml` にコピーします。
133
- また、 `.env.prod` を作成して、以下の値を登録します。
134
-
135
- ```
136
- SITE_NAME: テストサイト
137
- URL_BASE: https://example.com
138
- GTAG_ID: G-xxxx
139
- ```
140
-
141
- GitHub のリポジトリで、`settings > Secrets and variables > Actions` から、以下の変数を登録します。
142
-
143
- * `AWS_ACCESS_KEY_ID`
144
- * `AWS_SECRET_ACCESS_KEY_ID`
145
- * `S3_URL`
package/bin/new CHANGED
@@ -10,7 +10,7 @@ mkdir -p "$(pwd)/src/image"
10
10
  echo "create src/image"
11
11
 
12
12
  mkdir "$(pwd)/.cache"
13
- echo "{}" > "$(pwd)/.cache/index.json"
13
+ echo "[]" > "$(pwd)/.cache/index.json"
14
14
 
15
15
  echo 'dist/*
16
16
  node_modules/
@@ -23,6 +23,9 @@ echo '{
23
23
  "url_base": "http://localhost:8000",
24
24
  "src_dir": "src",
25
25
  "dist_dir": "dist",
26
- "distribute_raw": "image"
26
+ "distribute_raw": "image",
27
+ "helper": "helper/index.js"
27
28
  }' > "$(pwd)/blog.json"
28
29
  echo "create blog.json"
30
+
31
+ cp -R "$(pwd)/node_modules/@tenjuu99/blog/src-sample/" "$(pwd)/src"
package/lib/filter.js CHANGED
@@ -1,8 +1,7 @@
1
- import * as helper from '../helper/index.js'
1
+ import helper from '../lib/helper.js'
2
2
  import includeFilter from './includeFilter.js'
3
3
  import { srcDir } from './dir.js'
4
4
  import config from './config.js'
5
- console.log(config)
6
5
 
7
6
  /**
8
7
  * @param {string} text
@@ -10,19 +9,23 @@ console.log(config)
10
9
  * @return {text}
11
10
  */
12
11
  const replaceVariablesFilter = (text, variables) => {
13
- const matched = [...text.matchAll(/{{\s?([\w\d-_\(\)]+)\s?}}/g)]
14
- const replace = Object.fromEntries(matched.map(match => [match[1].toLowerCase(), match[0]]))
12
+ const matched = [...text.matchAll(/(\\)?{{\s?([\w\d\s,-_\(\)]+)\s?}}/g)]
13
+ const replace = Object.fromEntries(matched.map(match => [match[2].toLowerCase(), {replace: match[0], backslash: match[1]}]))
15
14
  let replaced = text
16
15
  for (const elm in replace) {
17
- const toBeReplace = replace[elm]
18
- const toBeReplaceScript = toBeReplace.match(/([\w\d_-]+)\((.+)\)/)
19
- if (toBeReplaceScript) {
16
+ const toBeReplace = replace[elm].replace
17
+ const toBeReplaceScript = toBeReplace.match(/([\w\d_]+)\((.*)\)/)
18
+
19
+ if (replace[elm].backslash) { // escape variable syntax
20
+ const removeBackslash = replace[elm].replace.replace(/\\/, '')
21
+ replaced = replaced.replaceAll(toBeReplace, removeBackslash)
22
+ } else if (toBeReplaceScript) { // execute helper
20
23
  const func = toBeReplaceScript[1]
21
- const variable = toBeReplaceScript[2]
24
+ const args = toBeReplaceScript[2].split(',').map(v => variables[v.trim()] ?? undefined)
22
25
  if (!helper[func]) {
23
- throw new Exception('helper function is missing. function name: ' + func);
26
+ throw new Error('helper function is missing. function name: ' + func);
24
27
  }
25
- const replaceText = helper[func](variables[variable.toLowerCase()])
28
+ const replaceText = helper[func].call(null, ...args)
26
29
  replaced = replaced.replaceAll(toBeReplace, replaceText)
27
30
  } else {
28
31
  replaced = replaced.replaceAll(toBeReplace, variables[elm])
@@ -129,13 +132,7 @@ const replaceScriptFilter = async (text, variables) => {
129
132
  }
130
133
  })
131
134
  for (const script of scripts) {
132
- let helperMerged = {...helper}
133
- // env.HELPER が定義されていれば追加ヘルパーとして扱う
134
- if (config.helper) {
135
- const additional = await import(`${srcDir}/${config.helper}`)
136
- helperMerged = Object.assign(helperMerged, additional)
137
- }
138
- let result = new Function('helper', 'variables', script.script)(helperMerged, variables)
135
+ let result = new Function('helper', 'variables', script.script)(helper, variables)
139
136
  if (result instanceof Promise) {
140
137
  result = await result
141
138
  }
package/lib/helper.js ADDED
@@ -0,0 +1,12 @@
1
+ import * as helperDefault from '../helper/index.js'
2
+ import config from './config.js'
3
+ import { srcDir } from './dir.js'
4
+
5
+ let helper = {...helperDefault}
6
+
7
+ if (config['helper']) {
8
+ const helperAdditional = await import(`${srcDir}/${config.helper}`)
9
+ helper = Object.assign(helper, helperAdditional)
10
+ }
11
+
12
+ export default helper
package/lib/render.js CHANGED
@@ -16,6 +16,7 @@ const render = async (templateName, data) => {
16
16
  markdown = await includeFilter(markdown)
17
17
  markdown = await replaceIfFilter(markdown, data)
18
18
  markdown = await replaceScriptFilter(markdown, data)
19
+ markdown = replaceVariablesFilter(markdown, data)
19
20
  data.markdown = data.__filetype === 'md' ? marked.parse(markdown) : markdown
20
21
 
21
22
  return replaceVariablesFilter(template, data)
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@tenjuu99/blog",
3
- "version": "0.1.4",
3
+ "version": "0.1.7",
4
4
  "description": "blog template",
5
5
  "main": "index.js",
6
6
  "scripts": {
@@ -11,7 +11,7 @@
11
11
  "bin": {
12
12
  "generate": "bin/generate",
13
13
  "server": "bin/server",
14
- "new": "bin/new"
14
+ "create-blog": "bin/new"
15
15
  },
16
16
  "author": "AmashigeSeiji",
17
17
  "repository": {
@@ -26,5 +26,14 @@
26
26
  "type": "module",
27
27
  "engines": {
28
28
  "node": ">=21.7"
29
+ },
30
+ "files": [
31
+ "lib",
32
+ "bin",
33
+ "helper",
34
+ "src-sample"
35
+ ],
36
+ "publishConfig": {
37
+ "access": "public"
29
38
  }
30
39
  }
@@ -113,7 +113,7 @@ return variables.someVariable
113
113
  {/script}
114
114
  ```
115
115
 
116
- ## 追加ヘルパー
116
+ ## ヘルパー
117
117
 
118
118
  ヘルパー関数を作成します。
119
119
  ```
@@ -132,14 +132,10 @@ HELPER=helper/index.js
132
132
  追加したヘルパーを利用できます。
133
133
  <pre>
134
134
  // src-sample/pages/sample.md
135
- &lt;script type="ssg">
136
- return helper.additionalHelper()
137
- &lt;/script>
135
+ \{{ additionalHelper() }}
138
136
  </pre>
139
137
 
140
138
  実際に出力させると次の行のとおりです。
141
139
  ```
142
- <script type="ssg">
143
- return helper.additionalHelper()
144
- </script>
140
+ {{additionalHelper()}}
145
141
  ```
package/.env.prod.sample DELETED
@@ -1,8 +0,0 @@
1
- SITE_NAME=test_blog
2
- GTAG_ID=
3
- URL_BASE=https://amashigeseiji.github.io/blog_template
4
- RELATIVE_PATH=/tenjuu99-blog
5
- SRC_DIR=src-sample
6
- DIST_DIR=dist
7
- DISTRIBUTE_RAW=image
8
- HELPER=helper/index.js
package/.env.sample DELETED
@@ -1,8 +0,0 @@
1
- SITE_NAME=test_blog
2
- GTAG_ID=
3
- URL_BASE=http://localhost:8000
4
- RELATIVE_PATH=
5
- SRC_DIR=src-sample
6
- DIST_DIR=dist
7
- DISTRIBUTE_RAW=image
8
- HELPER=helper/index.js
@@ -1,51 +0,0 @@
1
- name: Build html and deploy to S3
2
- on:
3
- push:
4
- branches:
5
- - main
6
- jobs:
7
- build:
8
- runs-on: ubuntu-latest
9
- steps:
10
- - name: Checkout
11
- uses: actions/checkout@master
12
-
13
- - name: npm install
14
- run: npm install --production
15
-
16
- - name: Build
17
- run: npm run generate:prod
18
-
19
- - name: Deploy
20
- env:
21
- AWS_ACCESS_KEY_ID: ${{ secrets.AWS_ACCESS_KEY_ID }}
22
- AWS_SECRET_ACCESS_KEY: ${{ secrets.AWS_SECRET_ACCESS_KEY }}
23
- run: |
24
- aws s3 sync \
25
- --region ap-northeast-1 \
26
- --exact-timestamps \
27
- --exclude .gitignore \
28
- --exclude '*.css' \
29
- --exclude 'image/' \
30
- --delete \
31
- --metadata-directive REPLACE \
32
- --cache-control "max-age=86400, no-cache, public" \
33
- dist/ s3://${{ secrets.S3_URL }}/
34
-
35
- aws s3 sync \
36
- --region ap-northeast-1 \
37
- --exact-timestamps \
38
- --exclude .gitignore \
39
- --delete \
40
- --metadata-directive REPLACE \
41
- --cache-control "max-age=31536000, public" \
42
- dist/css/ s3://${{ secrets.S3_URL }}/css/
43
-
44
- aws s3 sync \
45
- --region ap-northeast-1 \
46
- --exact-timestamps \
47
- --exclude .gitignore \
48
- --delete \
49
- --metadata-directive REPLACE \
50
- --cache-control "max-age=86400, public" \
51
- dist/image/ s3://${{ secrets.S3_URL }}/image/
@@ -1,52 +0,0 @@
1
- # Simple workflow for deploying static content to GitHub Pages
2
- name: Deploy static content to Pages
3
-
4
- on:
5
- push:
6
- branches:
7
- - main
8
- workflow_dispatch:
9
-
10
- # Sets permissions of the GITHUB_TOKEN to allow deployment to GitHub Pages
11
- permissions:
12
- contents: read
13
- pages: write
14
- id-token: write
15
-
16
- # Allow only one concurrent deployment, skipping runs queued between the run in-progress and latest queued.
17
- # However, do NOT cancel in-progress runs as we want to allow these production deployments to complete.
18
- concurrency:
19
- group: "pages"
20
- cancel-in-progress: false
21
-
22
- jobs:
23
- deploy:
24
- environment:
25
- name: github-pages
26
- url: ${{ steps.deployment.outputs.page_url }}
27
- runs-on: ubuntu-latest
28
- steps:
29
- - name: Checkout
30
- uses: actions/checkout@master
31
-
32
- - name: Use nodejs
33
- uses: actions/setup-node@v4
34
- with:
35
- node-version: '22.x'
36
-
37
- - name: npm install
38
- run: npm install --omit=dev
39
-
40
- - name: Build
41
- run: cp blog.json.prod blog.json && npm run generate
42
-
43
- - name: Setup Pages
44
- uses: actions/configure-pages@v4
45
- - name: Upload artifact
46
- uses: actions/upload-pages-artifact@v3
47
- with:
48
- # Upload dist
49
- path: './dist/'
50
- - name: Deploy to GitHub Pages
51
- id: deployment
52
- uses: actions/deploy-pages@v4
package/.gitignore DELETED
@@ -1,9 +0,0 @@
1
- node_modules/
2
- dist/*
3
- !.gitignore
4
- !favicon.ico
5
- data/index.json
6
- .DS_Store
7
-
8
- .env
9
- .cache/
package/.node-version DELETED
@@ -1 +0,0 @@
1
- 22.7.0
package/blog.json DELETED
@@ -1,8 +0,0 @@
1
- {
2
- "site_name": "test",
3
- "url_base": "http://localhost:8000",
4
- "src_dir": "src-sample",
5
- "dist_dir": "dist",
6
- "distribute_raw": "image",
7
- "helper": "helper/index.js"
8
- }
package/blog.json.prod DELETED
@@ -1,9 +0,0 @@
1
- {
2
- "site_name": "blog/sample",
3
- "url_base": "https://amashigeseiji.github.io/tenjuu99-blog",
4
- "relative_path": "/tenjuu99-blog",
5
- "src_dir": "src-sample",
6
- "dist_dir": "dist",
7
- "distribute_raw": "image",
8
- "helper": "helper/index.js"
9
- }
package/helper/add.js DELETED
@@ -1,3 +0,0 @@
1
- export function hogehoge() {
2
- return 'hogehoge'
3
- }
@@ -1,67 +0,0 @@
1
- /**
2
- * @param {string} condition
3
- * @params {object} variables
4
- * @return {bool}
5
- */
6
- const ifConditionEvaluator = (condition, variables) => {
7
- if (condition.includes('=')) {
8
- const segmented = condition.match(/(?<left>[\S]+)\s(?<operator>!=|==)\s(?<right>[\S]+)/)
9
- let {left, operator, right} = segmented.groups
10
- if (variables.hasOwnProperty(left)) {
11
- left = variables[left]
12
- } else {
13
- try {
14
- left = eval(left)
15
- } catch (e) {
16
- left = undefined
17
- }
18
- }
19
- if (variables.hasOwnProperty(right)) {
20
- right = variables[right]
21
- } else {
22
- try {
23
- right = eval(right)
24
- } catch (e) {
25
- right = undefined
26
- }
27
- }
28
- switch (operator) {
29
- case '==':
30
- return left == right
31
- case '!=':
32
- return left != right
33
- }
34
- } else {
35
- if (variables.hasOwnProperty(condition)) {
36
- return !!variables[condition]
37
- }
38
- return false
39
- }
40
- }
41
-
42
- const ifRegexp =
43
- new RegExp(/(\{|<)if\s(?<condition>[\s\S]+?)(}|>)(?<content>[\s\S]*?)((\{|<)else(\}|>)(?<elsecontent>[\s\S]*?))?(\{<)\/if(>|})/g)
44
-
45
- /**
46
- * @param {string} text
47
- * @param {object} variables
48
- * @returns {string}
49
- */
50
- const replaceIfFilter = (text, variables) => {
51
- const matched = [...text.matchAll(ifRegexp)]
52
- for (const item of matched) {
53
- const target = item[0]
54
- const content = item.groups.content
55
- const elseContent = item.groups.elsecontent
56
- if (ifConditionEvaluator(item.groups.condition, variables)) {
57
- text = text.replace(target, content)
58
- } else if (elseContent) {
59
- text = text.replace(target, elseContent)
60
- } else {
61
- text = text.replace(target, '')
62
- }
63
- }
64
- return text
65
- }
66
-
67
- export default replaceIfFilter
@@ -1,71 +0,0 @@
1
- import * as helper from '../helper/index.js'
2
- import vm from 'vm'
3
-
4
- /**
5
- * 配列を再帰的に順不同リストに変換する
6
- * @param {Array|string} arrayOrText
7
- * @returns {mixed}
8
- */
9
- const arrayToList = (arrayOrText) => {
10
- if (typeof arrayOrText === 'string') {
11
- return `<li>${arrayOrText}</li>`
12
- }
13
- if (Array.isArray(arrayOrText)) {
14
- let resultListText = '<ul>'
15
- for (const item of arrayOrText) {
16
- if (Array.isArray(item)) {
17
- resultListText += `<li>${arrayToList(item)}</li>`
18
- } else {
19
- resultListText += `<li>${item}</li>`
20
- }
21
- }
22
- resultListText += '</ul>'
23
- arrayOrText = resultListText
24
- }
25
- return arrayOrText
26
- }
27
-
28
- const replaceScriptFilter = async (text, variables) => {
29
- let replaced = text
30
- const scriptRegexp = new RegExp(/({script}|\<script\s.*type="ssg".*>)(?<script>[\s\S]*?)(\{\/script}|\<\/script>)/g)
31
- const scripts = [...text.matchAll(scriptRegexp)].map((matched) => {
32
- return {
33
- replace: matched[0],
34
- script: matched.groups.script.trim("\n"),
35
- }
36
- })
37
- const context = vm.createContext({
38
- helper,
39
- variables,
40
- })
41
- for (const script of scripts) {
42
- const s = new vm.Script(script.script)
43
- console.log(script.script)
44
- console.log(s)
45
- console.log('------------------------------------------------')
46
- const func = vm.runInContext(script, context)
47
- console.log(func)
48
- let result = await func(variables, helper)
49
- if (result instanceof Promise) {
50
- result = await result
51
- }
52
- if (Array.isArray(result)) {
53
- result = arrayToList(result)
54
- } else if (typeof result === 'object') {
55
- const resultText = []
56
- for (const key in result) {
57
- resultText.push(`<h3>${key}</h3>`)
58
- if (Array.isArray(result[key])) {
59
- resultText.push(arrayToList(result[key]))
60
- } else {
61
- resultText.push(`<p>${result[key]}</p>`)
62
- }
63
- }
64
- result = resultText.join('\n')
65
- }
66
- replaced = replaced.replace(script.replace, result)
67
- }
68
- return replaced
69
- }
70
-
71
- export default replaceScriptFilter
package/performance.js DELETED
@@ -1,22 +0,0 @@
1
- "use strict"
2
- import distribute from './lib/distribute.js'
3
- import { indexing, allData, deleted } from './lib/indexer.js'
4
- import { srcDir, distDir } from './lib/dir.js'
5
-
6
- process.env.FORCE_BUILD = true
7
- const doBuild = async () => {
8
- const start = performance.now()
9
- await indexing()
10
- await distribute(allData, deleted, srcDir, distDir)
11
- const end = performance.now()
12
- return end - start
13
- }
14
- const times = 100
15
- let executed = 0
16
- for (let i = 0; i < times; i++) {
17
- // console.log(await executed())
18
- const buildTime = await doBuild()
19
- executed += (buildTime)
20
- console.log(buildTime)
21
- }
22
- console.log('build average: 100 times: ' + (executed/times) + "ms")
File without changes
File without changes
File without changes
File without changes
@@ -1,11 +0,0 @@
1
- ---
2
- title: abc
3
- url: /abc
4
- published: 2024-08-31
5
- ---
6
- hoge
7
- hoge
8
-
9
-
10
- abc
11
- dc
@@ -1,3 +0,0 @@
1
- ## fuga
2
-
3
- これは変数がないです
@@ -1,8 +0,0 @@
1
- ---
2
- title: hoge
3
- url: /hoge
4
- published: 2024/03/19 00:00
5
- ifTrueVariable: true
6
- ---
7
-
8
- hoge
File without changes
File without changes
@@ -1 +0,0 @@
1
- これは [post](/post) 配下にあります
File without changes