pob 10.13.1 → 10.16.0

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/CHANGELOG.md CHANGED
@@ -3,6 +3,53 @@
3
3
  All notable changes to this project will be documented in this file.
4
4
  See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
5
5
 
6
+ # [10.16.0](https://github.com/christophehurpeau/pob/compare/pob@10.15.0...pob@10.16.0) (2022-05-31)
7
+
8
+
9
+ ### Features
10
+
11
+ * **deps:** update dependency eslint to v8.15.0 ([#1277](https://github.com/christophehurpeau/pob/issues/1277)) ([245b369](https://github.com/christophehurpeau/pob/commit/245b36992ca45f7f10ebcdb039badafc2740a6fe))
12
+ * **deps:** update dependency eslint to v8.16.0 ([#1290](https://github.com/christophehurpeau/pob/issues/1290)) ([e62d102](https://github.com/christophehurpeau/pob/commit/e62d102178e494d2009d225a365f4e62c692da4c))
13
+ * **deps:** update lerna monorepo to v5 (major) ([#1292](https://github.com/christophehurpeau/pob/issues/1292)) ([049f8c9](https://github.com/christophehurpeau/pob/commit/049f8c936d6b621077f7da932cf6b271bf93026b))
14
+
15
+
16
+
17
+
18
+
19
+ # [10.15.0](https://github.com/christophehurpeau/pob/compare/pob@10.14.0...pob@10.15.0) (2022-04-30)
20
+
21
+
22
+ ### Bug Fixes
23
+
24
+ * **pob:** fix ejs workflow for npm publish ([42ddb67](https://github.com/christophehurpeau/pob/commit/42ddb6791e97cfa06d9b6651c165fa717bfac9b2))
25
+
26
+
27
+ ### Features
28
+
29
+ * **pob:** improve readme with more badges ([b766c11](https://github.com/christophehurpeau/pob/commit/b766c11709bb0349beb1492b8f1860b65d87e73f))
30
+
31
+
32
+
33
+
34
+
35
+ # [10.14.0](https://github.com/christophehurpeau/pob/compare/pob@10.13.1...pob@10.14.0) (2022-04-30)
36
+
37
+
38
+ ### Bug Fixes
39
+
40
+ * **pob:** fix readme repository parser ([0aed381](https://github.com/christophehurpeau/pob/commit/0aed3812e753c9affe6b1db4ca3c70812c6182a6))
41
+
42
+
43
+ ### Features
44
+
45
+ * **pob:** add rootIgnorePatterns option in format-lint generator ([8baecc3](https://github.com/christophehurpeau/pob/commit/8baecc30735a576b8e60006bbe265aed076d9435))
46
+ * **pob:** initial config for release-please in monorepo ([72f4fc5](https://github.com/christophehurpeau/pob/commit/72f4fc50446a6f455e851f0fda4a351d9921fa74))
47
+ * remove useless dependencies cache ([f84c525](https://github.com/christophehurpeau/pob/commit/f84c52577e90a03ef3adb87b02ee1772b8acc74f))
48
+
49
+
50
+
51
+
52
+
6
53
  ## [10.13.1](https://github.com/christophehurpeau/pob/compare/pob@10.13.0...pob@10.13.1) (2022-04-30)
7
54
 
8
55
  **Note:** Version bump only for package pob
@@ -168,9 +168,13 @@ export default class PobAppGenerator extends Generator {
168
168
 
169
169
  this.composeWith('pob:common:remove-old-dependencies');
170
170
 
171
+ const enableReleasePlease =
172
+ !inLerna && this.appConfig.testing && this.appConfig.ci;
173
+
171
174
  if (this.appConfig.type !== 'remix') {
172
175
  this.composeWith('pob:common:testing', {
173
176
  enable: this.appConfig.testing,
177
+ enableReleasePlease,
174
178
  testing: this.appConfig.testing,
175
179
  typescript: babel,
176
180
  documentation: false,
@@ -60,9 +60,17 @@ export default class CommonLintGenerator extends Generator {
60
60
  desc: 'list of app types',
61
61
  });
62
62
 
63
+ this.option('rootIgnorePaths', {
64
+ type: String,
65
+ required: false,
66
+ defaults: '',
67
+ desc: 'list of ignore paths to add',
68
+ });
69
+
63
70
  this.option('ignorePaths', {
64
71
  type: String,
65
72
  required: false,
73
+ defaults: '',
66
74
  desc: 'list of ignore paths to add',
67
75
  });
68
76
 
@@ -125,6 +133,9 @@ export default class CommonLintGenerator extends Generator {
125
133
  };
126
134
 
127
135
  if (!inLerna || inLerna.root || this.options.monorepo) {
136
+ const rootIgnorePatterns = new Set(
137
+ this.options.rootIgnorePaths.split('\n').filter(Boolean),
138
+ );
128
139
  const ignorePatterns = new Set(
129
140
  this.options.ignorePaths.split('\n').filter(Boolean),
130
141
  );
@@ -151,6 +162,7 @@ export default class CommonLintGenerator extends Generator {
151
162
  yarnNodeLinker: this.options.yarnNodeLinker,
152
163
  workspaces: pkg.workspaces,
153
164
  hasApp: this.options.hasApp,
165
+ rootIgnorePatterns: [...rootIgnorePatterns],
154
166
  ignorePatterns: [...ignorePatterns],
155
167
  },
156
168
  );
@@ -8,6 +8,9 @@ CHANGELOG.md
8
8
  /.pnp.*
9
9
  <% } -%>
10
10
  <% } -%>
11
+ <% for (let ignorePattern of rootIgnorePatterns) { -%>
12
+ <%= ignorePattern %>
13
+ <% } -%>
11
14
  <% if (workspaces) { -%>
12
15
  <% for (let workspace of workspaces) { -%>
13
16
  <% if (ignorePatterns) { -%>
@@ -1,5 +1,4 @@
1
1
  import Generator from 'yeoman-generator';
2
- import inLerna from '../../../utils/inLerna.js';
3
2
  import * as packageUtils from '../../../utils/package.js';
4
3
 
5
4
  export default class CommonReleaseGenerator extends Generator {
@@ -33,34 +32,11 @@ export default class CommonReleaseGenerator extends Generator {
33
32
  });
34
33
  }
35
34
 
36
- async prompting() {
37
- this.isReleasePleaseEnabled =
38
- this.options.enable &&
39
- this.fs.exists(
40
- this.destinationPath('.github/workflows/release-please.yml'),
41
- );
42
-
43
- if (
44
- this.options.enable &&
45
- !process.env.CI &&
46
- !this.isReleasePleaseEnabled
47
- ) {
48
- const { enableReleasePlease } = await this.prompt({
49
- type: 'confirm',
50
- name: 'enableReleasePlease',
51
- message: 'Would you like to enable release please ?',
52
- default: true,
53
- });
54
- this.isReleasePleaseEnabled = enableReleasePlease;
55
- }
56
- }
57
-
58
35
  writing() {
59
36
  const pkg = this.fs.readJSON(this.destinationPath('package.json'));
60
37
 
61
- const isReleasePleaseEnabled = this.isReleasePleaseEnabled;
62
38
  const isStandardVersionEnabled =
63
- this.options.enable && !isReleasePleaseEnabled;
39
+ this.options.enable && !!pkg.devDependencies?.['standard-version'];
64
40
 
65
41
  if (!isStandardVersionEnabled) {
66
42
  packageUtils.removeDevDependencies(pkg, ['standard-version']);
@@ -87,24 +63,13 @@ export default class CommonReleaseGenerator extends Generator {
87
63
  }
88
64
  }
89
65
 
90
- if (!isReleasePleaseEnabled) {
91
- if (
92
- this.fs.exists(
93
- this.destinationPath('.github/workflows/release-please.yml'),
94
- )
95
- ) {
96
- this.fs.delete(
97
- this.destinationPath('.github/workflows/release-please.yml'),
98
- );
99
- }
100
- } else {
101
- this.fs.copyTpl(
102
- this.templatePath('release-please.yml.ejs'),
66
+ if (
67
+ this.fs.exists(
68
+ this.destinationPath('.github/workflows/release-please.yml'),
69
+ )
70
+ ) {
71
+ this.fs.delete(
103
72
  this.destinationPath('.github/workflows/release-please.yml'),
104
- {
105
- isLerna: !!inLerna,
106
- publish: !pkg.private,
107
- },
108
73
  );
109
74
  }
110
75
 
@@ -19,6 +19,12 @@ export default class CommonTestingGenerator extends Generator {
19
19
  desc: 'enable testing',
20
20
  });
21
21
 
22
+ this.option('enableReleasePlease', {
23
+ type: Boolean,
24
+ defaults: true,
25
+ desc: 'enable release-please',
26
+ });
27
+
22
28
  this.option('ci', {
23
29
  type: Boolean,
24
30
  required: true,
@@ -60,6 +66,7 @@ export default class CommonTestingGenerator extends Generator {
60
66
  if (!inLerna || inLerna.root) {
61
67
  this.composeWith('pob:core:ci', {
62
68
  enable: this.options.ci,
69
+ enableReleasePlease: this.options.enableReleasePlease,
63
70
  testing: this.options.enable,
64
71
  build: this.options.typescript,
65
72
  typescript: this.options.typescript,
@@ -1,5 +1,6 @@
1
1
  import fs from 'fs';
2
2
  import Generator from 'yeoman-generator';
3
+ import inLerna from '../../../utils/inLerna.js';
3
4
  import * as packageUtils from '../../../utils/package.js';
4
5
  import { copyAndFormatTpl } from '../../../utils/writeAndFormat.js';
5
6
 
@@ -13,6 +14,12 @@ export default class CoreCIGenerator extends Generator {
13
14
  desc: 'enable ci',
14
15
  });
15
16
 
17
+ this.option('enableReleasePlease', {
18
+ type: Boolean,
19
+ defaults: true,
20
+ desc: 'enable release-please',
21
+ });
22
+
16
23
  this.option('build', {
17
24
  type: Boolean,
18
25
  defaults: true,
@@ -62,6 +69,28 @@ export default class CoreCIGenerator extends Generator {
62
69
  });
63
70
  }
64
71
 
72
+ async prompting() {
73
+ const pkg = this.fs.readJSON(this.destinationPath('package.json'));
74
+
75
+ this.isReleasePleaseEnabled =
76
+ this.options.enableReleasePlease &&
77
+ !pkg.devDependencies?.['standard-version'];
78
+
79
+ if (
80
+ this.options.enableReleasePlease &&
81
+ !process.env.CI &&
82
+ !this.isReleasePleaseEnabled
83
+ ) {
84
+ const { enableReleasePlease } = await this.prompt({
85
+ type: 'confirm',
86
+ name: 'enableReleasePlease',
87
+ message: 'Would you like to enable release please ?',
88
+ default: true,
89
+ });
90
+ this.isReleasePleaseEnabled = enableReleasePlease;
91
+ }
92
+ }
93
+
65
94
  default() {
66
95
  if (fs.existsSync(this.destinationPath('.circleci'))) {
67
96
  fs.rmdirSync(this.destinationPath('.circleci'), { recursive: true });
@@ -83,6 +112,14 @@ export default class CoreCIGenerator extends Generator {
83
112
  typescript: this.options.typescript,
84
113
  codecov: this.options.codecov,
85
114
  supportsNode14: !this.options.isApp,
115
+
116
+ isReleasePleaseEnabled: this.isReleasePleaseEnabled,
117
+ publishSinglePackage: this.isReleasePleaseEnabled && !pkg.private,
118
+ publishMonorepo:
119
+ this.isReleasePleaseEnabled &&
120
+ inLerna &&
121
+ inLerna.root &&
122
+ inLerna.pobConfig?.project?.type === 'lib',
86
123
  },
87
124
  );
88
125
  } else {
@@ -14,18 +14,7 @@ jobs:
14
14
  with:
15
15
  node-version: 16
16
16
 
17
- - name: Cache dependencies
18
- uses: actions/cache@v3
19
- with:
20
- path: |
21
- .yarn/unplugged
22
- .yarn/install-state.gz
23
- key: v2-dependencies--${{ matrix.node-version }}-${{ runner.OS }}-${{ hashFiles('yarn.lock') }}
24
- restore-keys: |
25
- v2-dependencies--${{ matrix.node-version }}-${{ runner.OS }}-
26
- v2-dependencies--${{ matrix.node-version }}-
27
-
28
- - name: Check Dependencies
17
+ - name: Install Dependencies
29
18
  run: yarn install --immutable --immutable-cache
30
19
 
31
20
  <% if (typedoc) { -%>
@@ -17,36 +17,14 @@ jobs:
17
17
  uses: actions/setup-node@v3
18
18
  with:
19
19
  node-version: ${{ matrix.node-version }}
20
+ registry-url: 'https://registry.npmjs.org'
20
21
 
21
- <% if (packageManager !== 'npm') { -%>
22
- - name: Cache dependencies
23
- uses: actions/cache@v3
24
- with:
25
- <% if (packageManager === 'yarn') { -%>
26
- path: |
27
- .yarn/unplugged
28
- .yarn/install-state.gz
29
- <% } else { -%>
30
- path: node_modules
31
- <% } -%>
32
- key: v2-dependencies--${{ matrix.node-version }}-${{ runner.OS }}-${{ hashFiles('yarn.lock') }}
33
- restore-keys: |
34
- v2-dependencies--${{ matrix.node-version }}-${{ runner.OS }}-
35
- v2-dependencies--${{ matrix.node-version }}-
36
-
37
- <% } -%>
38
22
  <% if (packageManager === 'yarn') { -%>
39
- - name: Check Dependencies
23
+ - name: Install Dependencies
40
24
  run: yarn install --immutable --immutable-cache
41
25
  <% } else if (packageManager === 'npm') { -%>
42
- - name: Install Latest Npm
43
- run: npm install -g npm@next-7
44
-
45
26
  - name: Install Dependencies
46
27
  run: npm ci
47
- <% } else { -%>
48
- - name: Install Dependencies
49
- run: yarn install --prefer-offline --pure-lockfile
50
28
  <% } -%>
51
29
 
52
30
  <% if (checks) { -%>
@@ -99,3 +77,22 @@ jobs:
99
77
  if: startsWith(matrix.node-version, '16.')
100
78
  run: <%= packageManager === 'npm' ? 'npx' : 'yarn run' %> repository-check-dirty
101
79
  <% } -%>
80
+
81
+ <% if (isReleasePleaseEnabled) { -%>
82
+ - uses: GoogleCloudPlatform/release-please-action@v3
83
+ if: ${{ startsWith(matrix.node-version, '16.') && github.ref == 'refs/heads/main' }}
84
+ id: release
85
+ with:
86
+ token: ${{ secrets.GH_TOKEN }}
87
+ release-type: node
88
+ package-name: release-please-action
89
+
90
+ <% if (publishSinglePackage) { -%>
91
+
92
+ # publish:
93
+ - run: npm publish
94
+ if: ${{ startsWith(matrix.node-version, '16.') && github.ref == 'refs/heads/main' && steps.release.outputs.release_created }}
95
+ env:
96
+ NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }}
97
+ <% } -%>
98
+ <% } -%>
@@ -242,8 +242,12 @@ export default class PobLibGenerator extends Generator {
242
242
 
243
243
  this.composeWith('pob:common:remove-old-dependencies');
244
244
 
245
+ const enableReleasePlease =
246
+ !inLerna && this.pobjson.testing && this.pobjson.testing.ci;
247
+
245
248
  this.composeWith('pob:common:testing', {
246
249
  enable: this.pobjson.testing,
250
+ enableReleasePlease,
247
251
  testing: this.pobjson.testing,
248
252
  typescript: withBabel,
249
253
  documentation: !!this.pobjson.documentation,
@@ -274,7 +278,6 @@ export default class PobLibGenerator extends Generator {
274
278
  documentation: !!this.pobjson.documentation,
275
279
  testing: !!this.pobjson.testing,
276
280
  ci: this.pobjson.testing && this.pobjson.testing.ci,
277
- // travisci: this.pobjson.testing && this.pobjson.testing.travisci,
278
281
  codecov: this.pobjson.testing && this.pobjson.testing.codecov,
279
282
  });
280
283
 
@@ -69,7 +69,7 @@ export default class LibReadmeGenerator extends Generator {
69
69
  repository &&
70
70
  repository.match(
71
71
  // eslint-disable-next-line unicorn/no-unsafe-regex
72
- /^(?:git@|https?:\/\/)(?:([^./:]+)(?:\.com)?:)?([^/:]+)\/([^./:]+)(?:.git)?/,
72
+ /^(?:git@|https?:\/\/)(?:([^./:]+)(?:\.com)?[/:])?([^/:]+)\/([^./:]+)(?:.git)?/,
73
73
  );
74
74
  const [, gitHost, gitAccount, gitName] = match || [];
75
75
  try {
@@ -94,6 +94,10 @@ export default class LibReadmeGenerator extends Generator {
94
94
  license: pkg.license,
95
95
  codecov: this.options.codecov,
96
96
  documentation: this.options.documentation,
97
+ documentationUrl:
98
+ this.options.documentation && gitHost === 'github'
99
+ ? `https://${gitAccount}.github.io/${gitName}/`
100
+ : undefined,
97
101
  testing: this.options.testing,
98
102
  content,
99
103
  },
@@ -11,10 +11,16 @@
11
11
  <p align="center">
12
12
  <% if (!privatePackage) { -%>
13
13
  <a href="https://npmjs.org/package/<%= packageName %>"><img src="https://img.shields.io/npm/v/<%= packageName %>.svg?style=flat-square"></a>
14
+ <a href="https://npmjs.org/package/<%= packageName %>"><img src="https://img.shields.io/npm/dw/<%= packageName %>.svg?style=flat-square"></a>
15
+ <a href="https://npmjs.org/package/<%= packageName %>"><img src="https://img.shields.io/node/v/<%= packageName %>.svg?style=flat-square"></a>
16
+ <a href="https://npmjs.org/package/<%= packageName %>"><img src="https://img.shields.io/npm/types/<%= packageName %>.svg?style=flat-square"></a>
14
17
  <% } if (gitHost === 'github') { -%>
15
18
  <% if (testing && codecov) { -%>
16
19
  <a href="https://codecov.io/gh/<%= gitAccount %>/<%= gitName %>"><img src="https://img.shields.io/codecov/c/github/<%= gitAccount %>/<%= gitName %>/master.svg?style=flat-square"></a>
17
20
  <% } -%>
21
+ <% if (documentationUrl) { -%>
22
+ <a href="<%= documentationUrl %>"><img src="https://img.shields.io/website.svg?down_color=lightgrey&down_message=offline&up_color=blue&up_message=online&url=<%= encodeURIComponent(documentationUrl) %>?style=flat-square"></a>
23
+ <% } -%>
18
24
  <% } -%>
19
25
  </p>
20
26
 
@@ -197,9 +197,15 @@ export default class PobMonorepoGenerator extends Generator {
197
197
 
198
198
  this.composeWith('pob:common:husky', {});
199
199
 
200
+ const isReleasePleaseEnabled =
201
+ this.pobLernaConfig.testing &&
202
+ this.pobLernaConfig.ci &&
203
+ !pkg.devDependencies?.['@pob/lerna-light'];
204
+
200
205
  this.composeWith('pob:common:testing', {
201
206
  monorepo: true,
202
207
  enable: this.pobLernaConfig.testing,
208
+ enableReleasePlease: isReleasePleaseEnabled,
203
209
  testing: this.pobLernaConfig.testing,
204
210
  typescript: this.pobLernaConfig.typescript,
205
211
  documentation: !!this.pobLernaConfig.documentation,
@@ -223,6 +229,11 @@ export default class PobMonorepoGenerator extends Generator {
223
229
  ]
224
230
  .filter(Boolean)
225
231
  .join('\n'),
232
+ rootIgnorePaths: [
233
+ isReleasePleaseEnabled && '/.release-please-manifest.json',
234
+ ]
235
+ .filter(Boolean)
236
+ .join('\n'),
226
237
  });
227
238
 
228
239
  this.composeWith('pob:lib:doc', {
@@ -254,6 +265,14 @@ export default class PobMonorepoGenerator extends Generator {
254
265
 
255
266
  this.composeWith('pob:common:remove-old-dependencies');
256
267
 
268
+ this.composeWith('pob:common:release', {
269
+ enable: this.pobLernaConfig.testing && this.pobLernaConfig.ci,
270
+ isReleasePleaseEnabled,
271
+ withBabel: this.pobLernaConfig.typescript,
272
+ documentation: this.pobLernaConfig.documentation,
273
+ updateOnly: this.options.updateOnly,
274
+ });
275
+
257
276
  this.composeWith('pob:monorepo:typescript', {
258
277
  enable: this.pobLernaConfig.typescript,
259
278
  isAppProject: this.options.isAppProject,
@@ -20,18 +20,7 @@ jobs:
20
20
  with:
21
21
  node-version: 14
22
22
 
23
- - name: Cache dependencies
24
- uses: actions/cache@v3
25
- with:
26
- path: |
27
- .yarn/unplugged
28
- .yarn/install-state.gz
29
- key: v2-dependencies--${{ matrix.node-version }}-${{ runner.OS }}-${{ hashFiles('yarn.lock') }}
30
- restore-keys: |
31
- v2-dependencies--${{ matrix.node-version }}-${{ runner.OS }}-
32
- v2-dependencies--${{ matrix.node-version }}-
33
-
34
- - name: Check Dependencies
23
+ - name: Install Dependencies
35
24
  run: yarn install --immutable --immutable-cache
36
25
 
37
26
  - name: New version (dry run)
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "pob",
3
- "version": "10.13.1",
3
+ "version": "10.16.0",
4
4
  "description": "Pile of bones, library generator with git/babel/typescript/typedoc/readme/jest",
5
5
  "keywords": [
6
6
  "skeleton"
@@ -39,15 +39,15 @@
39
39
  },
40
40
  "pob": {},
41
41
  "dependencies": {
42
- "@lerna/package-graph": "^4.0.0",
43
- "@lerna/project": "^4.0.0",
42
+ "@lerna/package-graph": "^5.0.0",
43
+ "@lerna/project": "^5.0.0",
44
44
  "@pob/eslint-config": "49.1.0",
45
45
  "@pob/eslint-config-typescript": "49.3.0",
46
46
  "@pob/eslint-config-typescript-react": "49.3.1",
47
47
  "@pob/sort-eslint-config": "^3.0.1",
48
48
  "@pob/sort-object": "^4.0.1",
49
49
  "@pob/sort-pkg": "^4.0.1",
50
- "eslint": "8.14.0",
50
+ "eslint": "8.16.0",
51
51
  "findup-sync": "^5.0.0",
52
52
  "git-remote-url": "^1.0.1",
53
53
  "github-username": "^6.0.0",
@@ -61,11 +61,11 @@
61
61
  "mem-fs-editor": "9.4.0",
62
62
  "minimist": "1.2.6",
63
63
  "parse-author": "2.0.0",
64
- "pob-dependencies": "6.25.2",
64
+ "pob-dependencies": "6.26.0",
65
65
  "prettier": "2.6.2",
66
66
  "semver": "7.3.7",
67
67
  "yeoman-environment": "3.9.1",
68
68
  "yeoman-generator": "5.6.1"
69
69
  },
70
- "gitHead": "cc8f94676eea6b7d99541e74ec99f8e0a942e1b4"
70
+ "gitHead": "6e909141a6d1ee895cfc0dfa6686512cfd7ba409"
71
71
  }
@@ -1,36 +0,0 @@
1
- name: release-please
2
-
3
- on:
4
- push:
5
- branches:
6
- - main
7
-
8
- jobs:
9
- release-please:
10
- runs-on: ubuntu-latest
11
- steps:
12
- - uses: GoogleCloudPlatform/release-please-action@v3
13
- id: release
14
- with:
15
- token: ${{ secrets.GH_TOKEN }}
16
- release-type: node
17
- package-name: release-please-action
18
-
19
- # publish:
20
- - uses: actions/checkout@v3
21
- # these if statements ensure that a publication only occurs when
22
- # a new release is created:
23
- if: ${{ steps.release.outputs.release_created }}
24
-
25
- - uses: actions/setup-node@v3
26
- with:
27
- node-version: 14
28
- registry-url: 'https://registry.npmjs.org'
29
- if: ${{ steps.release.outputs.release_created }}
30
- <% if (publish) { -%>
31
-
32
- - run: npm publish
33
- env:
34
- NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }}
35
- if: ${{ steps.release.outputs.release_created }}
36
- <% } -%>