From bd4217bf7cebb676a3942c5535a0980ebafe6091 Mon Sep 17 00:00:00 2001 From: Joe Workman Date: Wed, 15 Dec 2021 11:43:52 -0800 Subject: [PATCH 01/12] Test for docs --- docs/configuration.mdx | 24 ++++++++++++ docs/data-overview.mdx | 82 ++++++++++++++++++++++++++++++++++++++++ docs/getting-started.mdx | 15 ++++++++ docs/index.mdx | 43 +++++++++++++++++++++ docs/installation.mdx | 9 +++++ docs/templates.mdx | 44 +++++++++++++++++++++ docs/update-proton.mdx | 7 ++++ 7 files changed, 224 insertions(+) create mode 100644 docs/configuration.mdx create mode 100644 docs/data-overview.mdx create mode 100644 docs/getting-started.mdx create mode 100644 docs/index.mdx create mode 100644 docs/installation.mdx create mode 100644 docs/templates.mdx create mode 100644 docs/update-proton.mdx diff --git a/docs/configuration.mdx b/docs/configuration.mdx new file mode 100644 index 0000000..185bc96 --- /dev/null +++ b/docs/configuration.mdx @@ -0,0 +1,24 @@ +# Configuration + +At the root of your project you can create a config file called either `proton.yml` or `.proton.yml`. + +```yaml +autoindex: true +debug: false +defaultExt: html +minify: false +pretty: true +paths: + batch: sample/batch + data: sample/data + dist: sample/dist + layouts: sample/layouts + macros: sample/macros + pages: sample/pages + partials: sample/partials +layouts: + default: default.html + rules: + subfolder: subfolder.html + blog: blog.html +``` diff --git a/docs/data-overview.mdx b/docs/data-overview.mdx new file mode 100644 index 0000000..e50f867 --- /dev/null +++ b/docs/data-overview.mdx @@ -0,0 +1,82 @@ +# Data Overview + +Storing data inside Proton is very flexible to work with Manu different workflows. By default, data is stored in YAML and JSON files inside of the `data` folder. However, this folder is configurable. + +### Default data.yml/json + +Data stored in the in the `data.yml` or `data.json` files are special in that they are stored at the top level of that global data structure. For example, let's look at this YAML data. + +```yaml +project: Proton - CLI Tool for compiling web pages +version: 1.0.0 +``` + +You will be able to insert this data into your page content via standard mustache syntax: `{{ project }}` and `{{ version }}` + +### Data Hierarchy + +There are many ways to create hierarchy within your data. + +Inside of your default data file (see above), you can add your own hierarchy inside of the yaml/json. + +```yaml +level1: + level2A: + propA: lorem ipsum + propB: lorem ipsum + level2B: + propA: lorem ipsum + propB: lorem ipsum +``` + +The above data would be the same as if you were to create a file named `level1.yml` with the following content. + +```yaml +level2A: + propA: lorem ipsum + propB: lorem ipsum +level2B: + propA: lorem ipsum + propB: lorem ipsum +``` + +The last way would be to add a folder structure into the mix. If you create a folder inside your data folder named `level1`, then crate yaml files for each level2 object: `level1/level2A.yml` and `level1/level2B.yml`. Each of these files would contain their data. + +```yaml +propA: lorem ipsum +propB: lorem ipsum +``` + +For all of the example above you can access the data just like you would traditionally with mustache templates: `{{ level1.level2A.propB }}` + +Twig provides many logic based functions like `for` loops that allow you iterate through data to create content dynamically. + +### Front Matter Data + +You can define data via YAML as frontmatter on any page. Data defined inside of the frontmatter is specific to just that page. Any values defined will overwrite any global data stored. + +There are a few special variables that can be defined inside of your frontmatter. + +* `layout`: defines the layout to use for the page. If no layout is defined the default layout defined in the configuration will be used. You can set this to `none` in order to have no default layout set. +* `output`: This sets the destination name of the page when it gets compiled into the configured `dist` folder. +* `batch`: Batch create pages based on an array of items in your data. This could allow you to create multiple items (such as products) based on the same page but with different data defined within your data. + +Example: + +``` +--- +layout: default.html +title: My awesome webpage +--- + +My Page Content... +``` + +### Debugging Data + +You can use the `data` command with proton to analyze the data that proton will use to build your pages. This can help you visualize how proton builds the data strucute. You can also pass an optional `--page` parameter in order to take into account a page's front matter so you can see the exact data strcutre used to build a single page. + +```sh +$ proton data +$ proton data --page=subfolder/index.html +``` diff --git a/docs/getting-started.mdx b/docs/getting-started.mdx new file mode 100644 index 0000000..ca968c8 --- /dev/null +++ b/docs/getting-started.mdx @@ -0,0 +1,15 @@ +# Getting Started + +You can see an example of how to setup proton in the [sample folder](https://github.com/foundation/proton/tree/master/sample). You can also create a [proton.yml](https://github.com/foundation/proton/blob/master/proton.yml) configuration file. + +You can use the following command to create the default structure needed for proton. You can optionally add the `--config` option to generate a config file as well. + +```sh +$ proton init --config +``` + +Then you can run the following command to build your site. + +```sh +$ proton build +``` diff --git a/docs/index.mdx b/docs/index.mdx new file mode 100644 index 0000000..fbbdf5a --- /dev/null +++ b/docs/index.mdx @@ -0,0 +1,43 @@ +# Proton - CLI Tool for compiling web pages and email + +Just like an actual proton is only one part of an atom, Proton is just one piece of the core for your project. It is not intended to be a full fledged CMS. It does zero management of your JavaScript, CSS, Assets or any kind of API that you website may require. Proton can compile your webpage assets into HTML, PHP or whatever language you may require. + +This project is meant to replace the popular [panini](https://github.com/foundation/panini) site generator. + +``` +This project is in very early stages. Any feedback would be appreciated. + +PLEASE DO NOT USE THIS FOR PRODUCTION PROJECTS. BREAKING CHANGES MAY BE MADE AT ANY TIME FOR NOW +``` + +## Proton Features + +Here are a list of the main features of Proton and how it can help you. + +### Reduce NPM Dependencies + +Managing NPM dependencies has become a difficult task. Both of our development tools and front end libraries are managed by the same package manager. Too often we have to deal with dependency conflicts between libraries and tools that we want to use. Proton is built with PHP. This means that it's dependencies lay 100% outside of your project's NPM dependency chain. + +### Twig Templates + +Proton leverages [Twig](https://twig.symfony.com) to bring you a powerful, flexible and fast templating system. Check out the [Twig Templates for Designers](https://twig.symfony.com/doc/3.x/templates.html) docs. If you like Handlebars, you will be blown away with Twig. + +Twig templates can be written in multiple formats. Markdown and Pug will be compiled down to HTML. All other languages, like HTML and PHP, will pass through into the compiled webpages. + +You can add front matter to your templates in order to customize options and provide page specific data. + +### Template Inheritance + +There are 4 levels of templates that you can use: layouts, pages, partials and macros. + +Pages are the core template type. You will create pages for each public page that you want on your site (batching aside, see below). Each page can inherit from one layout. Partials and macros allow you to create reusable components that you can use across all of your pages. + +### Data Storage + +Data can be stored in either YAML or JSON files. You can have multiple data files named differently. All data files are stored in one giant data structure during page compilation. This means that every page has full access to all pages. + +Data stored in the YAML frontmatter on each page will override the global data. + +### Batch Generate Pages + +You can create a single page that can be used to generate multiple pages for each item within a data set. For example, if you can define an array of products inside of your data. You can then create a page for each product by applying these data fro each to the one page template that you created. diff --git a/docs/installation.mdx b/docs/installation.mdx new file mode 100644 index 0000000..75d0fbe --- /dev/null +++ b/docs/installation.mdx @@ -0,0 +1,9 @@ +# Installation + +Proton requires that you have [Composer](https://getcomposer.org) installed. It may be easiest to then install proton globally on your computer. You can do this with the following command. + +```sh +composer global require foundation/proton +``` + +Make sure that you add the composer global installation folder to your shell PATH. By default it should be in the following location: `~/.composer/vendor/bin` \ No newline at end of file diff --git a/docs/templates.mdx b/docs/templates.mdx new file mode 100644 index 0000000..358f666 --- /dev/null +++ b/docs/templates.mdx @@ -0,0 +1,44 @@ +# Template Overview + +Layouts are the highest level of template. These traditionally contain the base HTML for your webpage. This could include the page `` and the basic layouts for your webpages. You can have multiple layouts that can be used across your pages. A page can only have one layout. + +Layouts may also contain content blocks. These blocks of content can be overwritten in pages. For example, a layout may have a content block for the header, main content, sidebar and footer. These are on top of the data variables that you can also inject into your templates for further customization. + +Partials allow you to create reusable pieces of content that can be used across multiple pages or possible multiple times on that same page. Partials are great for navigation, CTAs, subscription forms and more. + +Lastly, macros are basically functions that allow you to pass parameters in order to generate content in your pages. You can use these macros as many times as you want. + +**Make sure that you thoroughly review the [Twig for Template Designers](https://twig.symfony.com/doc/3.x/templates.html) documentation.** + +### Default Content Block + +If no content blocks are defined in your page template, a default `content` block will be added so that you can leverage the content inside of your layouts. + +### Markdown + +In order to process content as markdown inside of a template, you simple need to make sure that the file extension of the template is `md`. Example: `template.md` + +You can also use markdown in parts of your template with a markdown filter. + +``` +{% markdown %} +### Header + +This is my content +{% endmarkdown %} +``` + +### Pug + +You can process a template using Pug simply by giving the file that `pug` extension. Example: `template.pug` + +### Page Destinations + +All templates will be named the exact same name in the exact same folder structure inside of the configured `dist` folder. There are the following exceptions: + +* All templates with `pug`, `twig` and `md` extensions will become `html` files by default. You can change this with the `defaultExt` configuration value. +* You can customize the path and filename that a page gets output to via the `output` parameter set inside of a page's frontmatter. + +### Page Formatting + +You can use the `pretty` and `minify` configuration values to determine if the output of a page's HTML will be minified or indented to look "pretty". diff --git a/docs/update-proton.mdx b/docs/update-proton.mdx new file mode 100644 index 0000000..7a82fe4 --- /dev/null +++ b/docs/update-proton.mdx @@ -0,0 +1,7 @@ +# Updating Proton + +Updating proton could not be easier. You simply need to run the `self-update` command to update to the most recent version. + +```sh +$ proton self-update +``` From 901dad5f6ad48c2bee0686f25ff8a992274cc4bf Mon Sep 17 00:00:00 2001 From: Joe Workman Date: Wed, 15 Dec 2021 11:54:28 -0800 Subject: [PATCH 02/12] docs config --- docs.json | 17 +++++++++++++++++ docs/{data-overview.mdx => data.mdx} | 0 docs/{installation.mdx => install.mdx} | 0 docs/{update-proton.mdx => update.mdx} | 0 4 files changed, 17 insertions(+) create mode 100644 docs.json rename docs/{data-overview.mdx => data.mdx} (100%) rename docs/{installation.mdx => install.mdx} (100%) rename docs/{update-proton.mdx => update.mdx} (100%) diff --git a/docs.json b/docs.json new file mode 100644 index 0000000..487745d --- /dev/null +++ b/docs.json @@ -0,0 +1,17 @@ +{ + "name": "Proton", + "theme": "#36B9B9", + "twitter": "foundationcss", + "sidebar": [ + ["Overview", "/"], + ["Installation", "/install"], + ["Getting Started", "/getting-started"], + ["Configuration", "/configuration"], + ["Templates Overview", "/templates"], + ["Data Overview", "/data"], + ["Updating Proton", "/update"] + ], + "navigation": [ + ["Foundation Framework", "https://get.foundation/"] + ] +} diff --git a/docs/data-overview.mdx b/docs/data.mdx similarity index 100% rename from docs/data-overview.mdx rename to docs/data.mdx diff --git a/docs/installation.mdx b/docs/install.mdx similarity index 100% rename from docs/installation.mdx rename to docs/install.mdx diff --git a/docs/update-proton.mdx b/docs/update.mdx similarity index 100% rename from docs/update-proton.mdx rename to docs/update.mdx From d392f5fb0f356a6b7df22f1dd1bcf3f3f677cb6f Mon Sep 17 00:00:00 2001 From: Joe Workman Date: Wed, 15 Dec 2021 11:58:19 -0800 Subject: [PATCH 03/12] update docs --- docs.json | 6 ++---- docs/index.mdx | 4 +++- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/docs.json b/docs.json index 487745d..d4bf14c 100644 --- a/docs.json +++ b/docs.json @@ -9,9 +9,7 @@ ["Configuration", "/configuration"], ["Templates Overview", "/templates"], ["Data Overview", "/data"], - ["Updating Proton", "/update"] - ], - "navigation": [ - ["Foundation Framework", "https://get.foundation/"] + ["Updating Proton", "/update"], + ["About Foundation", "https://get.foundation/"] ] } diff --git a/docs/index.mdx b/docs/index.mdx index fbbdf5a..77670a6 100644 --- a/docs/index.mdx +++ b/docs/index.mdx @@ -1,4 +1,6 @@ -# Proton - CLI Tool for compiling web pages and email +# Proton + +## CLI Tool for compiling web pages and email Just like an actual proton is only one part of an atom, Proton is just one piece of the core for your project. It is not intended to be a full fledged CMS. It does zero management of your JavaScript, CSS, Assets or any kind of API that you website may require. Proton can compile your webpage assets into HTML, PHP or whatever language you may require. From 13e80bb42de275fd62db792f93796e97e710ef5e Mon Sep 17 00:00:00 2001 From: Joe Workman Date: Wed, 15 Dec 2021 12:05:29 -0800 Subject: [PATCH 04/12] remove docs from Readme --- README.md | 222 ++----------------------------------------------- docs/index.mdx | 2 +- 2 files changed, 6 insertions(+), 218 deletions(-) diff --git a/README.md b/README.md index a923467..ff5b653 100644 --- a/README.md +++ b/README.md @@ -7,224 +7,12 @@ This project is meant to replace the popular [panini](https://github.com/foundat ``` This project is in very early stages. Any feedback would be appreciated. -PLEASE DO NOT USE THIS FOR PRODUCTION PROJECTS. BREAKING CHANGES MAY BE MADE AT ANY TIME FOR NOW +PLEASE DO NOT USE THIS FOR PRODUCTION PROJECTS. ``` -## Proton Features +## Documentation -Here are a list of the main features of Proton and how it can help you. +Check out the docs at -### Reduce NPM Dependencies - -Managing NPM dependencies has become a difficult task. Both of our development tools and front end libraries are managed by the same package manager. Too often we have to deal with dependency conflicts between libraries and tools that we want to use. Proton is built with PHP. This means that it's dependencies lay 100% outside of your project's NPM dependency chain. - -### Twig Templates - -Proton leverages [Twig](https://twig.symfony.com) to bring you a powerful, flexible and fast templating system. Check out the [Twig Templates for Designers](https://twig.symfony.com/doc/3.x/templates.html) docs. If you like Handlebars, you will be blown away with Twig. - -Twig templates can be written in multiple formats. Markdown and Pug will be compiled down to HTML. All other languages, like HTML and PHP, will pass through into the compiled webpages. - -You can add front matter to your templates in order to customize options and provide page specific data. - -### Template Inheritance - -There are 4 levels of templates that you can use: layouts, pages, partials and macros. - -Pages are the core template type. You will create pages for each public page that you want on your site (batching aside, see below). Each page can inherit from one layout. Partials and macros allow you to create reusable components that you can use across all of your pages. - -### Data Storage - -Data can be stored in either YAML or JSON files. You can have multiple data files named differently. All data files are stored in one giant data structure during page compilation. This means that every page has full access to all pages. - -Data stored in the YAML frontmatter on each page will override the global data. - -### Batch Generate Pages - -You can create a single page that can be used to generate multiple pages for each item within a data set. For example, if you can define an array of products inside of your data. You can then create a page for each product by applying these data fro each to the one page template that you created. - -## Installation - -Proton requires that you have [Composer](https://getcomposer.org) installed. It may be easiest to then install proton globally on your computer. You can do this with the following command. - -```sh -composer global require foundation/proton -``` - -Make sure that you add the composer global installation folder to your shell PATH. By default it should be in the following location: `~/.composer/vendor/bin` - -## Getting Started - -You can see an example of how to setup proton in the [sample folder](https://github.com/foundation/proton/tree/master/sample). You can also create a [proton.yml](https://github.com/foundation/proton/blob/master/proton.yml) configuration file. - -You can use the following command to create the default structure needed for proton. You can optionally add the `--config` option to generate a config file as well. - -```sh -$ proton init --config -``` - -Then you can run the following command to build your site. - -```sh -$ proton build -``` - -## Template Overview - -Layouts are the highest level of template. These traditionally contain the base HTML for your webpage. This could include the page `` and the basic layouts for your webpages. You can have multiple layouts that can be used across your pages. A page can only have one layout. - -Layouts may also contain content blocks. These blocks of content can be overwritten in pages. For example, a layout may have a content block for the header, main content, sidebar and footer. These are on top of the data variables that you can also inject into your templates for further customization. - -Partials allow you to create reusable pieces of content that can be used across multiple pages or possible multiple times on that same page. Partials are great for navigation, CTAs, subscription forms and more. - -Lastly, macros are basically functions that allow you to pass parameters in order to generate content in your pages. You can use these macros as many times as you want. - -**Make sure that you thoroughly review the [Twig for Template Designers](https://twig.symfony.com/doc/3.x/templates.html) documentation.** - -### Default Content Block - -If no content blocks are defined in your page template, a default `content` block will be added so that you can leverage the content inside of your layouts. - -### Markdown - -In order to process content as markdown inside of a template, you simple need to make sure that the file extension of the template is `md`. Example: `template.md` - -You can also use markdown in parts of your template with a markdown filter. - -``` -{% markdown %} -### Header - -This is my content -{% endmarkdown %} -``` - -### Pug - -You can process a template using Pug simply by giving the file that `pug` extension. Example: `template.pug` - -### Page Destinations - -All templates will be named the exact same name in the exact same folder structure inside of the configured `dist` folder. There are the following exceptions: - -* All templates with `pug`, `twig` and `md` extensions will become `html` files by default. You can change this with the `defaultExt` configuration value. -* You can customize the path and filename that a page gets output to via the `output` parameter set inside of a page's frontmatter. - -### Page Formatting - -You can use the `pretty` and `minify` configuration values to determine if the output of a page's HTML will be minified or indented to look "pretty". - -## Data Overview - -Storing data inside Proton is very flexible to work with Manu different workflows. By default, data is stored in YAML and JSON files inside of the `data` folder. However, this folder is configurable. - -### Default data.yml/json - -Data stored in the in the `data.yml` or `data.json` files are special in that they are stored at the top level of that global data structure. For example, let's look at this YAML data. - -```yaml -project: Proton - CLI Tool for compiling web pages -version: 1.0.0 -``` - -You will be able to insert this data into your page content via standard mustache syntax: `{{ project }}` and `{{ version }}` - -### Data Hierarchy - -There are many ways to create hierarchy within your data. - -Inside of your default data file (see above), you can add your own hierarchy inside of the yaml/json. - -```yaml -level1: - level2A: - propA: lorem ipsum - propB: lorem ipsum - level2B: - propA: lorem ipsum - propB: lorem ipsum -``` - -The above data would be the same as if you were to create a file named `level1.yml` with the following content. - -```yaml -level2A: - propA: lorem ipsum - propB: lorem ipsum -level2B: - propA: lorem ipsum - propB: lorem ipsum -``` - -The last way would be to add a folder structure into the mix. If you create a folder inside your data folder named `level1`, then crate yaml files for each level2 object: `level1/level2A.yml` and `level1/level2B.yml`. Each of these files would contain their data. - -```yaml -propA: lorem ipsum -propB: lorem ipsum -``` - -For all of the example above you can access the data just like you would traditionally with mustache templates: `{{ level1.level2A.propB }}` - -Twig provides many logic based functions like `for` loops that allow you iterate through data to create content dynamically. - -### Front Matter Data - -You can define data via YAML as frontmatter on any page. Data defined inside of the frontmatter is specific to just that page. Any values defined will overwrite any global data stored. - -There are a few special variables that can be defined inside of your frontmatter. - -* `layout`: defines the layout to use for the page. If no layout is defined the default layout defined in the configuration will be used. You can set this to `none` in order to have no default layout set. -* `output`: This sets the destination name of the page when it gets compiled into the configured `dist` folder. -* `batch`: Batch create pages based on an array of items in your data. This could allow you to create multiple items (such as products) based on the same page but with different data defined within your data. - -Example: - -``` ---- -layout: default.html -title: My awesome webpage ---- - -My Page Content... -``` - -### Debugging Data - -You can use the `data` command with proton to analyze the data that proton will use to build your pages. This can help you visualize how proton builds the data strucute. You can also pass an optional `--page` parameter in order to take into account a page's front matter so you can see the exact data strcutre used to build a single page. - -```sh -$ proton data -$ proton data --page=subfolder/index.html -``` - -## Configuration - -At the root of your project you can create a config file called either `proton.yml` or `.proton.yml`. - -```yaml -autoindex: true -debug: false -defaultExt: html -minify: false -pretty: true -paths: - batch: sample/batch - data: sample/data - dist: sample/dist - layouts: sample/layouts - macros: sample/macros - pages: sample/pages - partials: sample/partials -layouts: - default: default.html - rules: - subfolder: subfolder.html - blog: blog.html -``` - -## Updating Proton - -Updating proton could not be easier. You simply need to run the `self-update` command to update to the most recent version. - -```sh -$ proton self-update -``` +* [Installation](https://docs.page/foundation/proton/install) +* [Getting Started](https://docs.page/foundation/proton/getting-started) diff --git a/docs/index.mdx b/docs/index.mdx index 77670a6..9efa11d 100644 --- a/docs/index.mdx +++ b/docs/index.mdx @@ -9,7 +9,7 @@ This project is meant to replace the popular [panini](https://github.com/foundat ``` This project is in very early stages. Any feedback would be appreciated. -PLEASE DO NOT USE THIS FOR PRODUCTION PROJECTS. BREAKING CHANGES MAY BE MADE AT ANY TIME FOR NOW +PLEASE DO NOT USE THIS FOR PRODUCTION PROJECTS. ``` ## Proton Features From f37b9b2c7292aae36fd42066884d79fdd76ba5d7 Mon Sep 17 00:00:00 2001 From: Joe Workman Date: Wed, 15 Dec 2021 12:24:28 -0800 Subject: [PATCH 05/12] Update docs index --- docs/index.mdx | 7 ------- 1 file changed, 7 deletions(-) diff --git a/docs/index.mdx b/docs/index.mdx index 9efa11d..10cbe76 100644 --- a/docs/index.mdx +++ b/docs/index.mdx @@ -4,13 +4,6 @@ Just like an actual proton is only one part of an atom, Proton is just one piece of the core for your project. It is not intended to be a full fledged CMS. It does zero management of your JavaScript, CSS, Assets or any kind of API that you website may require. Proton can compile your webpage assets into HTML, PHP or whatever language you may require. -This project is meant to replace the popular [panini](https://github.com/foundation/panini) site generator. - -``` -This project is in very early stages. Any feedback would be appreciated. - -PLEASE DO NOT USE THIS FOR PRODUCTION PROJECTS. -``` ## Proton Features From 543e9cc71d4be746b3e8a9d07283faafbf1d718e Mon Sep 17 00:00:00 2001 From: Joe Workman Date: Wed, 15 Dec 2021 12:24:51 -0800 Subject: [PATCH 06/12] Udpate readme --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index ff5b653..65230c4 100644 --- a/README.md +++ b/README.md @@ -5,7 +5,7 @@ Just like an actual proton is only one part of an atom, Proton is just one piece This project is meant to replace the popular [panini](https://github.com/foundation/panini) site generator. ``` -This project is in very early stages. Any feedback would be appreciated. +This project is in beta. Any feedback would be appreciated. PLEASE DO NOT USE THIS FOR PRODUCTION PROJECTS. ``` From 31df56c9a231cc883bd331715f06460adbb69777 Mon Sep 17 00:00:00 2001 From: Joe Workman Date: Fri, 17 Dec 2021 12:12:02 -0800 Subject: [PATCH 07/12] asset directory support closes #7 --- app/Commands/Build.php | 6 ++++++ app/Proton/AssetManager.php | 35 ++++++++++++++++++++++++++++++++ app/Proton/Config.php | 1 + app/Proton/FilesystemManager.php | 15 ++++++++++++++ app/Proton/PageManager.php | 19 +++-------------- proton.yml | 3 ++- sample/assets/.htaccess | 1 + 7 files changed, 63 insertions(+), 17 deletions(-) create mode 100644 app/Proton/AssetManager.php create mode 100644 sample/assets/.htaccess diff --git a/app/Commands/Build.php b/app/Commands/Build.php index 78d6d4a..0913325 100644 --- a/app/Commands/Build.php +++ b/app/Commands/Build.php @@ -57,6 +57,12 @@ public function handle() $pageManger = new \App\Proton\PageManager($config, $data); $pageManger->compilePages(); + //---------------------------------- + // Copy Assets + //---------------------------------- + $this->info('Copying Assets.'); + $assetManger = new \App\Proton\AssetManager($config); + $assetManger->copyAssets(); $this->info('Build Complete.'); } diff --git a/app/Proton/AssetManager.php b/app/Proton/AssetManager.php new file mode 100644 index 0000000..fca08aa --- /dev/null +++ b/app/Proton/AssetManager.php @@ -0,0 +1,35 @@ +config = $config; + $this->paths = $config->settings->paths; + } + + public function copyAssets(): void + { + $fsManager = new FilesystemManager($this->config); + $assets = $fsManager->getAllFiles($this->paths->assets); + foreach ($assets as $asset) { + $from = $this->paths->assets .DIRECTORY_SEPARATOR. $asset; + $to = $this->paths->dist .DIRECTORY_SEPARATOR. $asset; + $dir = dirname($to); + if (!file_exists($dir)) { + mkdir($dir, 0777, true); + } + copy($from, $to); + } + } +} diff --git a/app/Proton/Config.php b/app/Proton/Config.php index f868014..f93d741 100644 --- a/app/Proton/Config.php +++ b/app/Proton/Config.php @@ -27,6 +27,7 @@ class Config ], "paths" => [ "dist" => "dist", + "assets" => "src/assets", "data" => "src/data", "layouts" => "src/layouts", "macros" => "src/macros", diff --git a/app/Proton/FilesystemManager.php b/app/Proton/FilesystemManager.php index 9526af9..6967400 100644 --- a/app/Proton/FilesystemManager.php +++ b/app/Proton/FilesystemManager.php @@ -23,6 +23,21 @@ public function printPaths(): void } } + public function getAllFiles(string $path): array + { + $directory = new \RecursiveDirectoryIterator($path); + $directory->setFlags(\RecursiveDirectoryIterator::SKIP_DOTS); + $iterator = new \RecursiveIteratorIterator($directory); + $files = []; + // The length of the pages folder name + / + $dirLength = strlen($path)+1; + foreach ($iterator as $info) { + // Remove the pages fodler name from the file name + $files[] = substr_replace($info->getPathname(), '', 0, $dirLength); + } + return $files; + } + public function pathsExist(): bool { // Check if all paths exist diff --git a/app/Proton/PageManager.php b/app/Proton/PageManager.php index 1cd37cd..c5896c6 100644 --- a/app/Proton/PageManager.php +++ b/app/Proton/PageManager.php @@ -30,7 +30,9 @@ public function __construct(Config $config, Data $data) public function compilePages(): void { - foreach ($this->getAllPages() as $pageName) { + $fsManager = new FilesystemManager($this->config); + $pages = $fsManager->getAllFiles($this->paths->pages); + foreach ($pages as $pageName) { $page = new Page($pageName, $this->config, $this->data); $loader = $this->createPageLoader($pageName, $page->content); if ($page->isBatch()) { @@ -67,19 +69,4 @@ private function initTemplateLoader(): FilesystemLoader $loader->addPath($this->paths->layouts, "layouts"); return $loader; } - - private function getAllPages(): array - { - $directory = new \RecursiveDirectoryIterator($this->paths->pages); - $directory->setFlags(\RecursiveDirectoryIterator::SKIP_DOTS); - $iterator = new \RecursiveIteratorIterator($directory); - $pages = []; - // The length of the pages folder name + / - $dirLength = strlen($this->paths->pages)+1; - foreach ($iterator as $info) { - // Remove the pages fodler name from the file name - $pages[] = substr_replace($info->getPathname(), '', 0, $dirLength); - } - return $pages; - } } diff --git a/proton.yml b/proton.yml index bc2679d..6c6e8fa 100644 --- a/proton.yml +++ b/proton.yml @@ -1,6 +1,7 @@ paths: - data: sample/data dist: sample/dist + assets: sample/assets + data: sample/data layouts: sample/layouts macros: sample/macros pages: sample/pages diff --git a/sample/assets/.htaccess b/sample/assets/.htaccess new file mode 100644 index 0000000..dee1157 --- /dev/null +++ b/sample/assets/.htaccess @@ -0,0 +1 @@ +# testing assets \ No newline at end of file From 7d5ec8eb36c47c11ca68f68a38d78eb8b700edc8 Mon Sep 17 00:00:00 2001 From: Joe Workman Date: Fri, 17 Dec 2021 12:21:35 -0800 Subject: [PATCH 08/12] Fixed batch data processing --- app/Proton/PageBatchWriter.php | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/app/Proton/PageBatchWriter.php b/app/Proton/PageBatchWriter.php index b490014..eaf61a0 100644 --- a/app/Proton/PageBatchWriter.php +++ b/app/Proton/PageBatchWriter.php @@ -20,7 +20,11 @@ public function processBatch(): void { $batchkey = $this->page->data[Page::BATCHKEY]; $batchData = $this->page->data[$batchkey]; - foreach ($batchData as $key => $data) { + foreach ($batchData as $key => $props) { + // merge batch data into the global data batch key + $data = $this->page->data; + $data['batch'] = $props; + $this->output = $this->render($data); $this->formatOutput(); From 1be2659f06937040161b2e95548d80e243bdaa90 Mon Sep 17 00:00:00 2001 From: Joe Workman Date: Fri, 17 Dec 2021 12:29:04 -0800 Subject: [PATCH 09/12] Config doc fix --- docs/configuration.mdx | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/docs/configuration.mdx b/docs/configuration.mdx index 185bc96..7d68fad 100644 --- a/docs/configuration.mdx +++ b/docs/configuration.mdx @@ -9,13 +9,13 @@ defaultExt: html minify: false pretty: true paths: - batch: sample/batch - data: sample/data - dist: sample/dist - layouts: sample/layouts - macros: sample/macros - pages: sample/pages - partials: sample/partials + dist: dist + assets: src/assets + data: src/data + layouts: src/layouts + macros: src/macros + pages: src/pages + partials: src/partials layouts: default: default.html rules: From a28b4cdd53adaacdd935949b0da649b7646d0245 Mon Sep 17 00:00:00 2001 From: Joe Workman Date: Fri, 17 Dec 2021 12:44:15 -0800 Subject: [PATCH 10/12] assets docs --- docs.json | 5 +++-- docs/assets.mdx | 13 +++++++++++++ 2 files changed, 16 insertions(+), 2 deletions(-) create mode 100644 docs/assets.mdx diff --git a/docs.json b/docs.json index d4bf14c..011abdb 100644 --- a/docs.json +++ b/docs.json @@ -7,8 +7,9 @@ ["Installation", "/install"], ["Getting Started", "/getting-started"], ["Configuration", "/configuration"], - ["Templates Overview", "/templates"], - ["Data Overview", "/data"], + ["Page & Templates", "/templates"], + ["Site Assets", "/assets"], + ["Adding Data", "/data"], ["Updating Proton", "/update"], ["About Foundation", "https://get.foundation/"] ] diff --git a/docs/assets.mdx b/docs/assets.mdx new file mode 100644 index 0000000..fa4afbb --- /dev/null +++ b/docs/assets.mdx @@ -0,0 +1,13 @@ +# Assets Overview + +Any file placed into the configured `assets` folder will be directly copied into the `dist` folder. The files at the top level will be copied into the top level of the dist folder. + +The assets folder is a perfect place to store all of your site assets. + +* images +* JavaScript +* CSS +* webmanifest +* .htaccess +* favicons +* So much more... From 4bd062ff7adbe37a54f89aac7e381bc6a8399e88 Mon Sep 17 00:00:00 2001 From: Joe Workman Date: Fri, 17 Dec 2021 13:26:33 -0800 Subject: [PATCH 11/12] Sitemap generation closes #5 --- app/Commands/Build.php | 19 +++++++++---- app/Proton/Config.php | 2 ++ app/Proton/Sitemap.php | 32 ++++++++++++++++++++++ composer.json | 1 + composer.lock | 61 +++++++++++++++++++++++++++++++++++++++++- docs.json | 1 + docs/configuration.mdx | 2 ++ docs/sitemap.mdx | 5 ++++ 8 files changed, 117 insertions(+), 6 deletions(-) create mode 100644 app/Proton/Sitemap.php create mode 100644 docs/sitemap.mdx diff --git a/app/Commands/Build.php b/app/Commands/Build.php index 0913325..e4bdfc8 100644 --- a/app/Commands/Build.php +++ b/app/Commands/Build.php @@ -36,13 +36,13 @@ public function handle() $this->error('Not all required paths exist to build site. You can run `proton init` to ensure everything is setup.'); return; } - $this->info('Cleaning previous builds.'); + $this->info('Cleaning previous builds'); $fsManager->cleanupDist(); //---------------------------------- // Load in Data //---------------------------------- - $this->info('Loading data.'); + $this->info('Loading data'); $data = new \App\Proton\Data($config); if ($config->settings->debug) { @@ -53,17 +53,26 @@ public function handle() //---------------------------------- // Process all pages //---------------------------------- - $this->info('Compiling Pages.'); + $this->info('Compiling Pages'); $pageManger = new \App\Proton\PageManager($config, $data); $pageManger->compilePages(); + //---------------------------------- + // Create Sitemap + //---------------------------------- + if ($config->settings->sitemap) { + $this->info('Building Sitemap'); + $sitemap = new \App\Proton\Sitemap($config); + $sitemap->write(); + } + //---------------------------------- // Copy Assets //---------------------------------- - $this->info('Copying Assets.'); + $this->info('Copying Assets'); $assetManger = new \App\Proton\AssetManager($config); $assetManger->copyAssets(); - $this->info('Build Complete.'); + $this->info('Build Complete'); } } diff --git a/app/Proton/Config.php b/app/Proton/Config.php index f93d741..12a94a7 100644 --- a/app/Proton/Config.php +++ b/app/Proton/Config.php @@ -15,10 +15,12 @@ class Config ]; const DEFAULTS = [ "defaultExt" => "html", + "domain" => "https://www.example.com", "autoindex" => true, "debug" => false, "pretty" => true, "minify" => false, + "sitemap" => true, "layouts" => [ "default" => "default.html", "rules" => [ diff --git a/app/Proton/Sitemap.php b/app/Proton/Sitemap.php new file mode 100644 index 0000000..6b78b99 --- /dev/null +++ b/app/Proton/Sitemap.php @@ -0,0 +1,32 @@ +config = $config; + } + + public function write(): void + { + $dir = $this->config->settings->paths->dist; + $fsManager = new FilesystemManager($this->config); + $assets = $fsManager->getAllFiles($dir); + $domain = $this->config->settings->domain; + $sitemap = new \samdark\sitemap\Sitemap($dir .DIRECTORY_SEPARATOR. self::SITEMAP); + foreach ($assets as $asset) { + $url = $domain .'/'. $asset; + $sitemap->addItem($url); + } + $sitemap->write(); + } +} diff --git a/composer.json b/composer.json index 0b82f81..bc0ae32 100644 --- a/composer.json +++ b/composer.json @@ -22,6 +22,7 @@ "laravel-zero/phar-updater": "^1.0.6", "michelf/php-markdown": "^1.9", "pug/twig": "^1.2", + "samdark/sitemap": "^2.4", "twig/twig": "^3.3", "webuni/front-matter": "^1.3", "wyrihaximus/html-compress": "^4.1" diff --git a/composer.lock b/composer.lock index 22bbf8e..50728f6 100644 --- a/composer.lock +++ b/composer.lock @@ -4,7 +4,7 @@ "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies", "This file is @generated automatically" ], - "content-hash": "99c6be4b20a6e3591ec0af9ccd4dc384", + "content-hash": "72cda96fd06ce41acc5617753e3648ad", "packages": [ { "name": "aptoma/twig-markdown", @@ -2245,6 +2245,65 @@ ], "time": "2021-05-02T17:13:06+00:00" }, + { + "name": "samdark/sitemap", + "version": "2.4.0", + "source": { + "type": "git", + "url": "https://github.com/samdark/sitemap.git", + "reference": "a7ba091766afeb5fad1ea3056b30f26c3a620962" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/samdark/sitemap/zipball/a7ba091766afeb5fad1ea3056b30f26c3a620962", + "reference": "a7ba091766afeb5fad1ea3056b30f26c3a620962", + "shasum": "" + }, + "require": { + "ext-xmlwriter": "*", + "php": ">=5.3.0" + }, + "require-dev": { + "phpunit/phpunit": "~4.4" + }, + "type": "library", + "autoload": { + "psr-4": { + "samdark\\sitemap\\": "" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Alexander Makarov", + "email": "sam@rmcreative.ru", + "homepage": "http://rmcreative.ru/" + } + ], + "description": "Sitemap and sitemap index builder", + "homepage": "https://github.com/samdark/sitemap", + "keywords": [ + "Sitemap" + ], + "support": { + "issues": "https://github.com/samdark/sitemap/issues", + "source": "https://github.com/samdark/sitemap" + }, + "funding": [ + { + "url": "https://github.com/samdark", + "type": "github" + }, + { + "url": "https://www.patreon.com/samdark", + "type": "patreon" + } + ], + "time": "2021-10-02T04:04:28+00:00" + }, { "name": "sebastian/cli-parser", "version": "1.0.1", diff --git a/docs.json b/docs.json index 011abdb..ce1f402 100644 --- a/docs.json +++ b/docs.json @@ -10,6 +10,7 @@ ["Page & Templates", "/templates"], ["Site Assets", "/assets"], ["Adding Data", "/data"], + ["Generate Sitemap", "/sitemap"], ["Updating Proton", "/update"], ["About Foundation", "https://get.foundation/"] ] diff --git a/docs/configuration.mdx b/docs/configuration.mdx index 7d68fad..6bd74bb 100644 --- a/docs/configuration.mdx +++ b/docs/configuration.mdx @@ -6,8 +6,10 @@ At the root of your project you can create a config file called either `proton.y autoindex: true debug: false defaultExt: html +domain: https://www.example.com minify: false pretty: true +sitemap: true paths: dist: dist assets: src/assets diff --git a/docs/sitemap.mdx b/docs/sitemap.mdx new file mode 100644 index 0000000..82984af --- /dev/null +++ b/docs/sitemap.mdx @@ -0,0 +1,5 @@ +# Generating a Sitemap + +By default, Proton will generate a `sitemap.xml` file for SEO. You can turn off this feature by setting the `sitemap` option in the config file to `false`. + +One important setting that you will need to make sure that you set is the `domain` setting. This setting should contain the root URL of your website. For example: `https://www.example.com`. From 49c001d76505eafcb686699473e9d3291287d940 Mon Sep 17 00:00:00 2001 From: Joe Workman Date: Fri, 17 Dec 2021 13:29:59 -0800 Subject: [PATCH 12/12] v0.4.0 assets + sitemap --- builds/proton | Bin 7230177 -> 7254535 bytes 1 file changed, 0 insertions(+), 0 deletions(-) diff --git a/builds/proton b/builds/proton index 992421454bd27a5a3769dcc086d1f07c36fbfae9..1f568d28b79e60f9552c76cfbd412e51d3e64249 100755 GIT binary patch delta 268587 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