Skip to content
New issue

Have a question about this project? # for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “#”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? # to your account

feat(*): automate parser listing #200

Draft
wants to merge 1 commit into
base: master
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
40 changes: 40 additions & 0 deletions .github/workflows/parser-listing.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
name: 'Parser Listing'
on:
push:
branches:
- master
pull_request:
types: ['ready_for_review', 'opened', 'synchronize', 'reopened']
env:
NPM_TOKEN: ${{ secrets.NPM_TOKEN }}
jobs:
list:
runs-on: ubuntu-latest
if: github.event.pull_request.draft == false
steps:
- uses: actions/checkout@main
- name: Extract branch name
shell: bash
run: echo "branch=${GITHUB_HEAD_REF:-${GITHUB_REF#refs/heads/}}" >> $GITHUB_OUTPUT
id: extract_branch
- name: Install
run: yarn install --frozen-lockfile
- name: Create Listing
run: yarn list-parsers
- uses: technote-space/get-diff-action@v6
id: diff
with:
FILES: |
SUMMARY.md
- name: Pushes parser list
uses: dmnemec/copy_file_to_another_repo_action@main
if: steps.diff.outputs.diff
env:
API_TOKEN_GITHUB: ${{ secrets.GH_PARSERS_TOKEN }}
with:
source_file: 'output/parsers.md'
destination_repo: 'Specifyapp/Documentation'
destination_folder: 'concepts'
user_email: 'allan.michay@gmail.com'
user_name: 'AllanMichay'
commit_message: 'feat(parsers): update parsers list'
Empty file added output/.gitkeep
Empty file.
106 changes: 106 additions & 0 deletions output/PARSERS.md

Large diffs are not rendered by default.

3 changes: 2 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,7 @@
"test": "jest --coverage --runInBand",
"generate:seeds": "ts-node ./tests/helper/generate.seed.ts",
"format": "prettier '**/*' -u -w",
"prepare": "git config --local core.hooksPath .hooks"
"prepare": "git config --local core.hooksPath .hooks",
"list-parsers": "node ./scripts/list-parsers.js"
}
}
15 changes: 8 additions & 7 deletions parsers/sort-by/README.md
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
# Sort By

## Description
This parser helps loop on several design tokens and sort them according to their respective key values.

This parser helps you loop on several design tokens and sort them according to their respective key values.

Learn more about how to configure Specify in the API documentation: [https://specifyapp.com/developers](https://specifyapp.com/developers).

Expand Down Expand Up @@ -160,16 +161,16 @@ type output = Array<{ [key: string]: any }>;
"value": {
"unit": "px",
"measure": 8
},
}
},
{
"name": "base-space-01",
"type": "measurement",
"value": {
"unit": "px",
"measure": 4
},
},
}
}
]
```

Expand All @@ -183,15 +184,15 @@ type output = Array<{ [key: string]: any }>;
"value": {
"unit": "px",
"measure": 4 // <---
},
}
},
{
"name": "base-space-02",
"type": "measurement",
"value": {
"unit": "px",
"measure": 8 // <---
},
},
}
}
]
```
2 changes: 1 addition & 1 deletion parsers/to-flutter/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

## Description

Format design tokens to create a theme compatible with the [Flutter specification](https://docs.flutter.dev/cookbook/design/themes).
This parser helps you format design tokens to create a theme compatible with the [Flutter specification](https://docs.flutter.dev/cookbook/design/themes).

Learn more about how to configure Specify in the API documentation: [https://specifyapp.com/developers](https://specifyapp.com/developers).

Expand Down
2 changes: 1 addition & 1 deletion parsers/to-tailwind/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

## Description

Format design tokens to create a theme compatible with the [TailwindCSS specification](https://tailwindcss.com/docs/theme).
This parser helps you format design tokens to create a theme compatible with the [TailwindCSS specification](https://tailwindcss.com/docs/theme).
The theme is also compatible with [WindiCSS](https://windicss.org/).

This parser creates a file containing the whole theme. It can then be used in the `tailwind.config.js`.
Expand Down
2 changes: 1 addition & 1 deletion parsers/to-theme-ui/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

## Description

Format design tokens to create a theme compatible with the [theme-ui specification](https://theme-ui.com/theme-spec).
This parser helps you format design tokens to create a theme compatible with the [theme-ui specification](https://theme-ui.com/theme-spec).

Learn more about how to configure Specify in the API documentation: [https://specifyapp.com/developers](https://specifyapp.com/developers).

Expand Down
2 changes: 1 addition & 1 deletion parsers/to-typescript-definition/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

## Description

Format design tokens to create their corresponding TypeScript types.
This parser helps you format design tokens to create their corresponding TypeScript types.

This parser generates TypeScript types corresponding to [Specify Token types](https://docs.specifyapp.com/concepts/token-types). All types respective values match the name of your design tokens returned by Specify.

Expand Down
118 changes: 118 additions & 0 deletions scripts/list-parsers.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,118 @@
const fs = require('fs');
const path = require('path');

const directoryPath = path.join(__dirname, '../', 'parsers');
let parsers = [];
const fileNames = fs.readdirSync(directoryPath);

const directories = fileNames.filter(fileName => !fileName.includes('.ts'));

parsers = directories.map(directory => {
const readmeParserPath = path.join(__dirname, '../', 'parsers', directory, 'README.md');
const parserContent = fs.readFileSync(readmeParserPath, { encoding: 'utf8', flag: 'r' });

const parserDescription = parserContent.match(/This parser helps you (.*)/)[1];
const capitalizedParserDescription =
parserDescription.charAt(0).toUpperCase() + parserDescription.slice(1);
const exampleLink = `https://github.com/Specifyapp/parsers/blob/master/parsers/${directory}/README.md#usage`;
const parserLink = `https://github.com/Specifyapp/parsers/blob/master/parsers/${directory}`;

return {
title: directory,
description: capitalizedParserDescription,
parserLink,
exampleLink,
};
});

const markdownFullPage = `---
description: >-
Parsers are functions allowing you to transform design tokens and assets
coming from Specify to fit your needs and company standards.
---

# Parsers

## Why you need parsers

<figure><img src="../front/documentation/.gitbook/assets/where-parsers-happen-dark.jpg" alt=""><figcaption><p>Parsers help you transform raw design tokens and assets returned by Specify to match your company standards</p></figcaption></figure>

By default, without any parsers, Specify will return your design data as raw data:

* Design tokens are returned in JSON
* Assets are returned as files

There are high chances you need to transform those design data to fit your needs. Parsers help you do just that.

## What are parsers?

Parsers are functions allowing you to transform design tokens and assets coming from Specify to fit your needs and company standards.

<figure><img src="../front/documentation/.gitbook/assets/how-parsers-work.jpg" alt=""><figcaption><p>An example output pipeline that pulls colors from Specify, sorts them alphabetically and transforms them as CSS Custom Properties</p></figcaption></figure>

A parser does the following job:

1. Receives design data as input
2. Transforms this design data
3. Returns the transformed data

The data returned by a parser can either be:

* Design data that can be used by another parser coming next in your transformation pipeline
* A file so it can be used by people, frameworks, or scripts

{% hint style="info" %}
Parsers are what make Specify powerful and flexible. They help you be in total control of the design data you pull from Specify.
{% endhint %}

Parsers are ordered and takes specific input to generate specific output. This way, we can easily test the input coming from the previous parser to check if the whole parsers process will work.

## Categories

Parsers are classified in 2 categories: technology and utility.

### Technology

Technology parsers help you transform your design tokens to specific technologies and formats (CSS Custom properties, SCSS, Tailwind, a Javascript theme object compatible with React Native...)

Some examples:

* [to-react-native](https://github.com/Specifyapp/parsers/tree/master/parsers/to-react-native)
* [to-css-custom-properties](https://github.com/Specifyapp/parsers/tree/master/parsers/to-css-custom-properties)
* [to-scss-variables](https://github.com/Specifyapp/parsers/tree/master/parsers/to-scss-variables)
* [to-tailwind](https://github.com/Specifyapp/parsers/tree/master/parsers/to-tailwind)

### Utility

Utility parsers take care of "smaller" transformation. Like converting a pixel value to \`rem\` or transforming a string to kebabcase.

Some examples:

* [convert-font](https://github.com/Specifyapp/parsers/tree/master/parsers/convert-font)
* [kebabcasify](https://github.com/Specifyapp/parsers/tree/master/parsers/kebabcasify)
* [px-to-rem](https://github.com/Specifyapp/parsers/tree/master/parsers/px-to-rem)

## All parsers available

All parsers are open source and available on [the following GitHub repository](https://github.com/Specifyapp/parsers).

`;

const markdownHeader = `| Parser | Description | Usage Example |
|---|---|---|`;

const parsersMarkdown = parsers.reduce((acc, currentParser) => {
const { title, description, exampleLink, parserLink } = currentParser;
if (!acc) {
return `${markdownHeader}
| [${title}](${parserLink}) | ${description} | [Example](${exampleLink}) |`;
}
return `${acc}
| [${title}](${parserLink}) | ${description} | [Example](${exampleLink}) |`;
}, '');

const summaryFilePath = path.join(__dirname, '../output/', 'parsers.md');
fs.writeFileSync(summaryFilePath, markdownFullPage + parsersMarkdown, {
encoding: 'utf8',
flag: 'w',
});