ultimate-jekyll-manager 0.0.1 → 0.0.3

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/.nvmrc ADDED
@@ -0,0 +1 @@
1
+ v20/*
package/LICENSE CHANGED
@@ -1,6 +1,6 @@
1
1
  MIT License
2
2
 
3
- Copyright (c) 2024 Jr. AI
3
+ Copyright (c) 2024 Ultimate Jekyll
4
4
 
5
5
  Permission is hereby granted, free of charge, to any person obtaining a copy
6
6
  of this software and associated documentation files (the "Software"), to deal
package/README.md CHANGED
@@ -1,2 +1,5 @@
1
1
  # ultimate-jekyll-manager
2
2
  All-in-one package for ultimate-jekyll
3
+
4
+ # Commands
5
+ * `npx uj setup && npm start` - Setup and start the project
@@ -0,0 +1,22 @@
1
+ // Libraries
2
+ const path = require('path');
3
+ const jetpack = require('fs-jetpack');
4
+
5
+ // Load package
6
+ const package = jetpack.read(path.join(__dirname, '../../', 'package.json'), 'json');
7
+ const project = jetpack.read(path.join(process.cwd(), 'package.json'), 'json');
8
+
9
+ module.exports = async function (options) {
10
+ // Log
11
+ console.log(`Cleaning up _site, .jekyll-cache, and .jekyll-metadata...`);
12
+
13
+ try {
14
+ // Delete _site, .jekyll-cache
15
+ jetpack.remove('_site');
16
+ jetpack.remove('site/.jekyll-cache');
17
+ jetpack.remove('site/.jekyll-metadata');
18
+
19
+ } catch (e) {
20
+ console.error(`Error during setup:`, e);
21
+ }
22
+ };
@@ -0,0 +1,51 @@
1
+ // Libraries
2
+ const path = require('path');
3
+ const jetpack = require('fs-jetpack');
4
+ const { execute } = require('node-powertools');
5
+
6
+ // Load package
7
+ const package = jetpack.read(path.join(__dirname, '../../', 'package.json'), 'json');
8
+ const project = jetpack.read(path.join(process.cwd(), 'package.json'), 'json');
9
+
10
+ module.exports = async function (options) {
11
+ // Log
12
+ console.log(`Installing Ultimate Jekyll Manager...`);
13
+
14
+ // Get type
15
+ const type = options._[1] || 'prod';
16
+
17
+ try {
18
+ // Install production
19
+ if (['prod', 'p', 'production'].includes(type)) {
20
+ // Log
21
+ console.log('Installing production...');
22
+
23
+ // Install
24
+ await install('npm uninstall ultimate-jekyll-manager');
25
+ await install('npm install ultimate-jekyll-manager@latest --save-dev');
26
+
27
+ // Return
28
+ return console.log('Production installation complete.');
29
+ }
30
+
31
+ // Install development
32
+ if (['dev', 'd', 'development', 'local', 'l'].includes(type)) {
33
+ // Log
34
+ console.log('Installing development...');
35
+
36
+ // Install
37
+ await install('npm uninstall ultimate-jekyll-manager');
38
+ await install('npm install ../../ITW-Creative-Works/ultimate-jekyll-manager --save-dev');
39
+
40
+ // Return
41
+ return console.log('Development installation complete.');
42
+ }
43
+
44
+ } catch (e) {
45
+ console.error(`Error during install:`, e);
46
+ }
47
+ };
48
+
49
+ function install(command) {
50
+ return execute(command, { log: true });
51
+ }
@@ -1,35 +1,63 @@
1
1
  // Libraries
2
2
  const path = require('path');
3
- const { gte, clean } = require('semver');
3
+ const jetpack = require('fs-jetpack');
4
+ const wonderfulVersion = require('wonderful-version');
4
5
  const { execute } = require('node-powertools');
5
6
  const NPM = require('npm-api');
7
+ const glob = require('glob').globSync;
6
8
 
7
9
  // Load package
8
- const package = require('../../package.json');
9
- const project = require(path.join(process.cwd(), 'package.json'));
10
+ const package = jetpack.read(path.join(__dirname, '../../', 'package.json'), 'json');
11
+ const project = jetpack.read(path.join(process.cwd(), 'package.json'), 'json');
12
+
13
+ // Dependency MAP
14
+ const DEPENDENCY_MAP = {
15
+ 'gulp': 'dev',
16
+ }
17
+
18
+ // File MAP
19
+ const FILE_MAP = {
20
+ 'hooks/postbuild.js': {overwrite: false},
21
+ 'hooks/prebuild.js': {overwrite: false},
22
+ }
10
23
 
11
24
  module.exports = async function (options) {
25
+ // Log
12
26
  console.log(`Welcome to Ultimate Jekyll v${package.version}!`);
13
27
 
14
- // Log
15
- console.log('package:', package);
16
- console.log('project:', project);
28
+ // Prefix project
29
+ project.dependencies = project.dependencies || {};
30
+ project.devDependencies = project.devDependencies || {};
17
31
 
18
32
  try {
19
33
  // Ensure this package is up-to-date
20
34
  await updateManager();
21
35
 
36
+ // Ensure proper node version
37
+ await ensureNodeVersion();
38
+
22
39
  // Run the setup
23
40
  await ensurePeerDependencies();
24
41
 
42
+ // Setup scripts
43
+ setupScripts();
44
+
45
+ // Build files
46
+ await buildSiteFiles();
47
+
48
+ // Check which locality we are using
49
+ checkLocality();
50
+
25
51
  } catch (e) {
26
- console.error(`Error during the prompt: ${e.message}`);
52
+ console.error(`Error during setup:`, e);
27
53
  }
28
54
  };
29
55
 
30
56
  async function updateManager() {
31
57
  const npm = new NPM();
32
58
 
59
+ // Get the latest version
60
+ const installedVersion = project.devDependencies['ultimate-jekyll-manager'];
33
61
  const latestVersion = await npm.repo('ultimate-jekyll-manager')
34
62
  .package()
35
63
  .then((pkg) => {
@@ -38,40 +66,155 @@ async function updateManager() {
38
66
  return '0.0.0';
39
67
  });
40
68
 
41
- // Compare the versions
42
- console.log('latestVersion:', latestVersion);
69
+ // Quit if local
70
+ if (installedVersion.startsWith('file:')) {
71
+ return console.log('Local version detected. Skipping update check.');
72
+ }
43
73
 
74
+ // Log
75
+ console.log('Installed Version:', installedVersion);
76
+ console.log('Latest Version:', latestVersion);
77
+
78
+ // Check if we need to update
79
+ if (wonderfulVersion.is(installedVersion, '>=', latestVersion)) {
80
+ return console.log('Ultimate Jekyll Manager is up-to-date.');
81
+ } else {
82
+ await install('ultimate-jekyll-manager', latestVersion);
83
+ }
84
+ }
85
+
86
+ async function ensureNodeVersion() {
87
+ const installedVersion = process.version;
88
+ const requiredVersion = package.engines.node;
89
+
90
+ // Log
91
+ console.log('Installed Node Version:', installedVersion);
92
+ console.log('Required Node Version:', requiredVersion);
93
+
94
+ // Check if we need to update
95
+ if (wonderfulVersion.is(installedVersion, '>=', requiredVersion)) {
96
+ return console.log('Node version is up-to-date.');
97
+ } else {
98
+ console.error(`Node version is out-of-date. Required version is ${requiredVersion}.`);
99
+ }
44
100
  }
45
101
 
46
102
  async function ensurePeerDependencies() {
47
- const requiredPeerDependencies = package.requiredPeerDependencies || {};
103
+ const requiredPeerDependencies = package.peerDependencies || {};
48
104
 
49
105
  // Loop through and make sure project has AT LEAST the required version
50
106
  for (const [dependency, version] of Object.entries(requiredPeerDependencies)) {
51
107
  const projectDependencyVersion = project.dependencies[dependency] || project.devDependencies[dependency];
108
+ const location = DEPENDENCY_MAP[dependency] === 'dev' ? '--save-dev' : '';
109
+
110
+ // Log
111
+ console.log('Checking peer dep:', dependency, '-->', projectDependencyVersion, '>=', version);
52
112
 
53
113
  // Install if not found
54
- if (!projectDependencyVersion) {
55
- await install(dependency, version);
56
- } else {
57
- // Clean the version and compare
58
- const cleanProjectVersion = clean(projectDependencyVersion);
59
- const cleanRequiredVersion = clean(version);
60
-
61
- if (!gte(cleanProjectVersion, cleanRequiredVersion)) {
62
- await install(dependency, version);
63
- }
114
+ if (
115
+ // Not found
116
+ !projectDependencyVersion
117
+ // Not the right version
118
+ || wonderfulVersion.is(projectDependencyVersion, '<', version)
119
+ ) {
120
+ await install(dependency, version, location);
64
121
  }
65
122
  }
66
123
  }
67
124
 
68
- function install(package, version) {
125
+ function setupScripts() {
126
+ // Setup the scripts
127
+ project.scripts = project.scripts || {};
128
+
129
+ // Setup the scripts
130
+ Object.keys(package.projectScripts).forEach((key) => {
131
+ project.scripts[key] = package.projectScripts[key];
132
+ });
133
+
134
+ // Save the project
135
+ jetpack.write(path.join(process.cwd(), 'package.json'), project);
136
+ }
137
+
138
+ function checkLocality() {
139
+ const installedVersion = project.devDependencies['ultimate-jekyll-manager'];
140
+
141
+ if (installedVersion.startsWith('file:')) {
142
+ console.warn('⚠️⚠️⚠️ You are using the local version of Ultimate Jekyll Manager. This WILL NOT WORK when published. ⚠️⚠️⚠️');
143
+ }
144
+ }
145
+
146
+ function install(package, version, location) {
69
147
  // Default to latest
70
148
  version || 'latest';
71
149
 
150
+ // Clean version if needed
151
+ version = version === 'latest' ? version : wonderfulVersion.clean(version);
152
+
72
153
  // Build the command
73
- let command = `npm install ${package}@${version}`;
154
+ let command = `npm install ${package}@${version} ${location || '--save'}`;
155
+
156
+ // Log
157
+ console.log('Installing:', command);
74
158
 
75
159
  // Execute
76
160
  return execute(command, { log: true })
161
+ .then(async () => {
162
+ // Read new project
163
+ const projectUpdated = jetpack.read(path.join(process.cwd(), 'package.json'), 'json');
164
+
165
+ // Log
166
+ console.log('Installed:', package, version);
167
+
168
+ // Update package object
169
+ project.dependencies = projectUpdated.dependencies;
170
+ project.devDependencies = projectUpdated.devDependencies;
171
+ });
172
+ }
173
+
174
+ function buildSiteFiles() {
175
+ // Loop through all files in /templates directory
176
+ const dir = path.join(__dirname, '..', 'templates');
177
+ const files = glob('**/*', {
178
+ cwd: dir,
179
+ dot: true,
180
+ nodir: true,
181
+ });
182
+
183
+ // Loop
184
+ for (const file of files) {
185
+ // Get the destination
186
+ const source = path.join(dir, file);
187
+ const destination = path.join(process.cwd(), file.replace('templates/', ''));
188
+ const filename = path.basename(destination);
189
+ const options = FILE_MAP[file] || {overwrite: true};
190
+
191
+ // Quit if file is '_'
192
+ if (filename === '_') {
193
+ continue;
194
+ }
195
+
196
+ // Check if the file exists
197
+ const exists = jetpack.exists(destination);
198
+
199
+ // Log
200
+ // console.log('File:', file);
201
+ // console.log('filename:', filename);
202
+ // console.log('options:', options);
203
+ // console.log('contents:', jetpack.read(source));
204
+ // console.log('source:', source);
205
+ // console.log('Destination:', destination);
206
+
207
+ // Skip if it exists
208
+ // console.log('---1');
209
+
210
+ if (exists && !options.overwrite) {
211
+ // console.log('---2');
212
+ continue;
213
+ }
214
+ // console.log('---3', jetpack.read(source));
215
+
216
+ // Copy the file
217
+ // console.log('Copying:', file, 'to', destination);
218
+ jetpack.copy(source, destination, { overwrite: true });
219
+ }
77
220
  }
@@ -1,5 +1,12 @@
1
- const package = require('../../package.json');
1
+ // Libraries
2
+ const path = require('path');
3
+ const jetpack = require('fs-jetpack');
4
+
5
+ // Load package
6
+ const package = jetpack.read(path.join(__dirname, '../../', 'package.json'), 'json');
7
+ const project = jetpack.read(path.join(process.cwd(), 'package.json'), 'json');
2
8
 
3
9
  module.exports = async function (options) {
10
+ // Log
4
11
  console.log(package.version);
5
12
  };
@@ -0,0 +1,305 @@
1
+ # Welcome to Ultimate Jekyll!
2
+ #
3
+ # This config file is meant for settings that affect your whole blog, values
4
+ # which you are expected to set up once and rarely edit after that. If you find
5
+ # yourself editing this file very often, consider using Jekyll's data files
6
+ # feature for the data you need to update frequently.
7
+ #
8
+ # For technical reasons, this file is *NOT* reloaded automatically when you use
9
+ # 'bundle exec jekyll serve'. If you change this file, please restart the server process.
10
+
11
+ # Site settings
12
+ # These are used to personalize your new site. If you look in the HTML files,
13
+ # you will see them accessed via {{ site.title }}, {{ site.email }}, and so on.
14
+ # You can create any custom variable you would like, and they will be accessible
15
+ # in the templates via {{ site.myvariable }}.
16
+
17
+ # Site configurations
18
+ url: "" # the base hostname & protocol for your site, e.g. http://example.com
19
+ baseurl: "" # the subpath of your site, e.g. /blog
20
+ test1: 1
21
+
22
+ # Custom Configuration
23
+ version: '1.0.0'
24
+ app: ''
25
+ meta:
26
+ title: "Title"
27
+ description: "Description"
28
+ og-images: "https://cdn.itwcreativeworks.com/assets/itw-creative-works/images/socials/itw-creative-works-brandmark-square-black-1024x1024.png"
29
+ keywords: "" # false or blank to disable, comma separated kws
30
+ viewport: "" # string, leave blank to use default
31
+ index: true # true | false
32
+ referrer: "" # string, leave blank to use default
33
+
34
+ launcher:
35
+ download: "" # string, example: https://example.com/download
36
+
37
+ cloudflare:
38
+ zone: ''
39
+
40
+ socials:
41
+ facebook: "" # string, example: somiibo
42
+ twitter: "" # string, example: somiibo
43
+ linkedin: "" # string, example: somiibo
44
+ youtube: "" # string, example: somiibo
45
+ instagram: "" # string, example: somiibo
46
+ tumblr: "" # string, example: somiibo
47
+ slack: "" # string, example: somiibo
48
+ discord: "" # string, example: gxAuKX6
49
+ github: "" # string, example: somiibo
50
+ dev: "" # string, example: somiibo
51
+ tiktok: "" # string, example: somiibo
52
+ twitch: "" # string, example: somiibo
53
+ soundcloud: "" # string, example: somiibo
54
+ spotify: "" # string, example: somiibo
55
+ mixcloud: "" # string, example: somiibo
56
+
57
+ download:
58
+ mac: '' # string, example: https://github.com/somiibo/download-server/releases/download/installer/Somiibo.dmg
59
+ windows: '' # string, example: https://github.com/somiibo/download-server/releases/download/installer/Somiibo-Setup.exe
60
+ linux-debian: '' # string, example: https://github.com/somiibo/download-server/releases/download/installer/Somiibo_amd64.deb
61
+ linux-snap: '' # string, example: https://snapcraft.io/somiibo
62
+ ios: '' # string, example: https://apps.apple.com/us/app/somiibo/id999999999
63
+ android: '' # string, example: https://play.google.com/store/apps/details?id=com.itwcreativeworks.somiibo
64
+
65
+ extension:
66
+ chrome: '' # string, example: https://chrome.google.com/webstore/detail/somiibo/opidlipnbfhpdenbnanplcalbdgoplnc
67
+ firefox: '' # string, example: https://addons.mozilla.org/en-US/firefox/addon/somiibo
68
+ opera: '' # string, example: https://addons.opera.com/en/extensions/details/somiibo
69
+ safari: '' # string, example: https://apps.apple.com/us/app/somiibo/id999999999
70
+ edge: '' # string, example: https://microsoftedge.microsoft.com/addons/detail/somiibo/opidlipnbfhpdenbnanplcalbdgoplnc
71
+
72
+ comments:
73
+ gisqus-repo: "Distalk/giscus" # string, example: somiibo/giscus
74
+ gisqus-repo-id: "R_kgDOJ-chGA" # string, example: R_kgDOJ-chGA
75
+ gisqus-category: "Giscus" # string, example: Giscus
76
+ gisqus-category-id: "DIC_kwDOJ-chGM4CYD4O" # string, example: DIC_kwDOJ-chGM4CYD4O
77
+
78
+ tracking:
79
+ google-analytics: false # false to disable, example: UA-123456789
80
+ facebook-pixel: false # false to disable, example: fbp-123456789
81
+ tiktok-pixel: false # false to disable, example: D4829D83H38929384H48
82
+
83
+ advertising:
84
+ google-adsense: "pub-7372939085773564" # false to disable, example: ca-pub-7372939085773564
85
+ google-adsense-display-slot: "9023354299" # example: 9023354299
86
+ google-adsense-in-article-slot: "7329067043" # example: 7329067043
87
+ google-adsense-in-feed-slot: "5986127415" # example: 5986127415
88
+ google-adsense-multiplex-slot: "8772072856" # example: 8772072856
89
+ cse-site-id: "5ad46a4c7412db0ae" # example: 5ad46a4c7412db0ae
90
+
91
+ email-marketing: # Get this information from Mailchimp > Audience > Manage Audience > Signup forms > Embedded forms > Then look at code
92
+ mailchimp-user-id: "06dd652b8c707fdf51ebcff20" # string, example: 06dd652b8c707fdf51ebcff20
93
+ mailchimp-list-name: "" # string, example: somiibo
94
+ mailchimp-list-id: "" # string, example: b3456e5ffd
95
+
96
+ contact:
97
+ email-support: "" # string, example: support@example.com
98
+ email-business: "" # string, example: hello@example.com
99
+ slapform-form-id: "" # string, example: abc123 (create one at https://slapform.com)
100
+ phone: "+1 (000) 000 - 0000" # string, example: +1 (000) 000 - 0000
101
+
102
+ brand:
103
+ name: "" # example: Google
104
+ type: "Corporation" # example: Corporation
105
+ description: "." # example: A search engine company.
106
+ logo-images: "https://cdn.itwcreativeworks.com/assets/itw-creative-works/images/logo/itw-creative-works-brandmark-black-1024x1024.png" # URL | LOCAL path, example: https://defaultogimage.com, /assets/img/og/og.png
107
+ logo-image-svg: "https://cdn.itwcreativeworks.com/assets/itw-creative-works/images/logo/itw-creative-works-brandmark-black-x.svg" # URL | LOCAL path, example: https://defaultogimage.com, /assets/img/og/og.svg
108
+ address-locality: "Los Angeles" # String | example: Los Angeles
109
+ address-country: "United States" # String | example: United States
110
+
111
+ manifest:
112
+ name: "" # example: Google Maps
113
+ short-name: "" # example: Maps
114
+ theme-color: "#ffffff" # example: #ffffff
115
+ background-color: "#ffffff" # example: #ffffff
116
+ display: "standalone" # example: standalone
117
+ start-url: "/?source=pwa" # example: /, /maps/?source=pwa
118
+ scope: "/" # example: /, /maps/
119
+ orientation: "portrait" # example: portrait,
120
+
121
+ schema:
122
+ breadcrumbs: true # true | false
123
+ brand: true # true | false
124
+ sitelinks: true # true | false
125
+
126
+ favicon:
127
+ path: "https://cdn.itwcreativeworks.com/assets/itw-creative-works/images/favicon" # example: /assets/images/favicon
128
+ safari-pinned-tab: "#5bbad5" # example: #5bbad5
129
+ msapp-tile-color: "#da532c" # example: #da532c"
130
+ theme-color: "#ffffff" # example: #ffffff
131
+
132
+ search:
133
+ enable: true # true | false
134
+
135
+ sitemap:
136
+ enable: true # true | false
137
+
138
+ settings:
139
+ include-app-head: true # true | false
140
+ include-app-foot: true # true | false
141
+ include-script-bundle: true # true | false
142
+ include-script-bundle-optimization: "async" # defer | async | ""
143
+ include-script-core: false # true | false
144
+ include-script-core-optimization: "async" # defer | async | ""
145
+ include-script-slapform: false # true | false
146
+ include-script-slapform-optimization: "async" # defer | async | ""
147
+ include-css-bundle: true # true | false
148
+ include-css-normalize: false # true | false
149
+ include-css-reset: false # true | false
150
+ include-css-defaults: true # true | false
151
+ include-html5shiv: true # true | false
152
+ include-socialsharekit: true # true | false
153
+ include-debug-performance: false # true | false
154
+ blog-post-image-class: "" # class will be applied to all blog post images using the master include
155
+ blog-author-image-class: "" # class will be applied to all blog author images using the master include
156
+ manager-configuration: "
157
+ {
158
+ libraries: {
159
+ firebase_app: {
160
+ enabled: true,
161
+ config: {
162
+ apiKey: '',
163
+ authDomain: '',
164
+ databaseURL: '',
165
+ projectId: '',
166
+ storageBucket: '',
167
+ messagingSenderId: '',
168
+ appId: '',
169
+ measurementId: '',
170
+ },
171
+ },
172
+ firebase_appCheck: {
173
+ enabled: false,
174
+ config: {
175
+ siteKey: '',
176
+ },
177
+ },
178
+ cookieconsent: {
179
+ enabled: true,
180
+ config: {
181
+ palette: {
182
+ popup: {
183
+ background: '#fd5631',
184
+ text: '#fff',
185
+ },
186
+ button: {
187
+ background: '#fff',
188
+ text: '#fd5631',
189
+ },
190
+ },
191
+ },
192
+ },
193
+ chatsy: {
194
+ enabled: true,
195
+ config: {
196
+ accountId: '',
197
+ chatId: '',
198
+ settings: {
199
+ openChatButton: {
200
+ background: '#fd5631',
201
+ text: '#fff',
202
+ },
203
+ },
204
+ },
205
+ },
206
+ sentry: {
207
+ enabled: true,
208
+ config: {
209
+ dsn: '',
210
+ release: '',
211
+ replaysSessionSampleRate: 0.01,
212
+ replaysOnErrorSampleRate: 0.01,
213
+ },
214
+ },
215
+ },
216
+ exitPopup: {
217
+ enabled: true,
218
+ config: {
219
+ timeout: 1000 * 60 * 60 * 4,
220
+ handler: null,
221
+ title: 'Want 50% off your gift?',
222
+ messages: 'There are some gifts on sale today for as much as 50% off. Click the button below to claim your discount!',
223
+ okButton: {
224
+ text: 'Claim 50% Discount',
225
+ link: 'https://giftly.app',
226
+ },
227
+ },
228
+ },
229
+ }
230
+ " # javascript object to set the Configuration object for Web Manager
231
+
232
+ # Custom admin dashboard pages
233
+ admin-dashboard: "{
234
+ pages: [
235
+ ]
236
+ }"
237
+
238
+ # Escape shortcuts
239
+ escapes:
240
+ underscore: "_"
241
+ asterisk: "*"
242
+ brace-left: "{"
243
+ brace-right: "}"
244
+ bracket-left: "["
245
+ bracket-right: "]"
246
+
247
+ # Blog & Pagination
248
+ permalink: /blog/:title
249
+ pagination:
250
+ enabled: true
251
+ per_pages: 6
252
+ offset: 0
253
+ limit: 0
254
+ permalink: /page/:num.html
255
+ title: :title - page :num
256
+ sort_field: 'date'
257
+ sort_reverse: true
258
+
259
+ # Jekyll Defaults
260
+ collections:
261
+ team:
262
+ title: Team Members
263
+ output: true
264
+ defaults:
265
+ - scope:
266
+ path: ''
267
+ type: team
268
+ values:
269
+ permalink: /team/:title
270
+
271
+ # Build settings
272
+ markdown: kramdown
273
+ plugins:
274
+ - jekyll-paginate-v2
275
+ - jekyll-liquify
276
+ - jekyll-uj-powertools
277
+ - jekyll-truthyfalsy
278
+
279
+ # Exclude from processing.
280
+ # The following items will not be processed, by default. Create a custom list
281
+ # to override the default setting.
282
+ exclude:
283
+ # DEFAULT
284
+ - Gemfile
285
+ - Gemfile.lock
286
+ - gulp_tasks
287
+ - gulpfile.js
288
+ - LICENSE
289
+ - node_modules
290
+ - npm-debug.log
291
+ - package.json
292
+ - package-lock.json
293
+ - README.md
294
+ - vendor/bundle/
295
+ - vendor/cache/
296
+ - vendor/gems/
297
+ - vendor/ruby/
298
+ - yarn.lock
299
+ # MASTER
300
+ - .placeholder
301
+ # APP
302
+
303
+ include:
304
+ # MASTER
305
+ - .well-known