diff --git a/.actrc b/.actrc deleted file mode 100644 index 85619c8b0a9..00000000000 --- a/.actrc +++ /dev/null @@ -1 +0,0 @@ --P ubuntu-latest=nektos/act-environments-ubuntu:18.04 \ No newline at end of file diff --git a/.babelrc b/.babelrc deleted file mode 100644 index 6720dbde263..00000000000 --- a/.babelrc +++ /dev/null @@ -1,11 +0,0 @@ -{ - "presets": [ - [ - "env", { - "targets": { - "node": "current" - } - } - ] - ] -} diff --git a/.codeclimate.yml b/.codeclimate.yml deleted file mode 100644 index c1684360115..00000000000 --- a/.codeclimate.yml +++ /dev/null @@ -1,58 +0,0 @@ -version: "2" -checks: - argument-count: - enabled: true - config: - threshold: 4 - complex-logic: - enabled: true - config: - threshold: 4 - file-lines: - enabled: false - method-complexity: - enabled: true - config: - threshold: 5 - method-count: - enabled: true - config: - threshold: 20 - method-lines: - enabled: false - nested-control-flow: - enabled: true - config: - threshold: 4 - return-statements: - enabled: true - config: - threshold: 4 - similar-code: - enabled: true - config: - threshold: #language-specific defaults. overrides affect all languages. - identical-code: - enabled: true - config: - threshold: #language-specific defaults. overrides affect all languages. -plugins: - fixme: - enabled: true - config: - strings: - - HACK - markdownlint: - enabled: false -exclude_patterns: -- "**/coverage/" -- "**/dist/" -- "**/www/" -- "**/node_modules/" -- "**/*.d.ts" -- "**/__tests__/" -- "**/__snapshots__/" -- "**/*.spec.ts" -- "**/*.spec.tsx" -- "**/*.test.ts" -- "**/*.test.tsx" \ No newline at end of file diff --git a/.eslintignore b/.eslintignore index adefedf46cf..2f72b20274e 100644 --- a/.eslintignore +++ b/.eslintignore @@ -1,3 +1,7 @@ +# Never lint test files +*.spec.ts +!*.pw.spec.ts + # Never lint node_modules node_modules @@ -5,4 +9,7 @@ node_modules dist # Never lint coverage output -coverage \ No newline at end of file +coverage + +# Never lint karma configs +karma.conf.cjs diff --git a/.eslintrc.js b/.eslintrc.js index 8712625260a..5d4b702fb7e 100644 --- a/.eslintrc.js +++ b/.eslintrc.js @@ -1,3 +1,85 @@ module.exports = { - extends: ["@microsoft/eslint-config-fast-dna", "prettier"], + root: true, + parser: "@typescript-eslint/parser", + plugins: ["@typescript-eslint", "import"], + extends: [ + "eslint:recommended", + "plugin:@typescript-eslint/eslint-recommended", + "plugin:@typescript-eslint/recommended", + "prettier" + ], + rules: { + "no-unused-vars": "off", + "no-extra-boolean-cast": "off", + "no-empty-function": "off", + "@typescript-eslint/no-empty-function": [ + "error", + { allow: ["asyncMethods", "methods"] }, + ], + "@typescript-eslint/no-use-before-define": "off", + "@typescript-eslint/typedef": "off", + "@typescript-eslint/explicit-function-return-type": "off", + "max-len": ["error", 140], + "import/order": "error", + "sort-imports": [ + "error", + { + ignoreCase: true, + ignoreDeclarationSort: true, + }, + ], + "comma-dangle": "off", + "@typescript-eslint/no-empty-interface": [ + "error", + { + allowSingleExtends: true, + }, + ], + "@typescript-eslint/camelcase": "off", + "@typescript-eslint/naming-convention": [ + "error", + { + selector: "default", + format: ["UPPER_CASE", "camelCase", "PascalCase"], + leadingUnderscore: "allow", + }, + { + selector: "property", + format: null, // disable for property names because of our foo__expanded convention for JSS + // TODO: I think we can come up with a regex that ignores variables with __ in them + }, + { + selector: "variable", + format: null, // disable for variable names because of our foo__expanded convention for JSS + // TODO: I think we can come up with a regex that ignores variables with __ in them + }, + { + selector: "interface", + format: ["PascalCase"], + custom: { + regex: "^I[A-Z]", + match: false, + }, + }, + ], + "@typescript-eslint/no-inferrable-types": "off", + "no-prototype-builtins": "off", + "no-fallthrough": "off", + "no-unexpected-multiline": "off", + "@typescript-eslint/no-unused-vars": ["warn", { args: "none" }], + "@typescript-eslint/no-explicit-any": "off", + }, + overrides: [ + { + files: ["**/*.js"], + extends: ["eslint:recommended"], + env: { + node: true, + "shared-node-browser": true, + }, + rules: { + "@typescript-eslint/no-var-requires": "off", + }, + }, + ], }; diff --git a/.github/CODEOWNERS b/.github/CODEOWNERS index f35d38ab23e..31002049187 100644 --- a/.github/CODEOWNERS +++ b/.github/CODEOWNERS @@ -5,43 +5,4 @@ # The last matching pattern has the most precendence. # These *code owners* will be the default owners for everything in the repository. -* @chrisdholt @janechu @nicholasrice - -# File type specific owners -# Markdown specific files -*.md @awentzel @chrisdholt @falkicon @EisenbergEffect -/docs/ @awentzel @chrisdholt @falkicon @EisenbergEffect - -# GitHub management -.github/ @awentzel @janechu @chrisdholt @nicholasrice -.github/workflows/ @awentzel @chrisdholt @nicholasrice - -# Build scripts -*.yml @awentzel @janechu @nicholasrice @chrisdholt @EisenbergEffect -build/ @janechu @nicholasrice @chrisdholt @awentzel @EisenbergEffect - -# Specifications -/specs/ @EisenbergEffect @chrisdholt @janechu @nicholasrice - -# Sites -/sites/fast-color-explorer/ @nicholasrice @janechu @bheston -/sites/fast-component-explorer/ @janechu @nicholasrice -/sites/website/ @awentzel @chrisdholt @falkicon @EisenbergEffect - -# Package specific owners - -# Tooling -/packages/tooling/fast-figma-plugin-msft/ @nicholasrice @bheston @janechu @EisenbergEffect -/packages/tooling/fast-tooling-react/ @janechu @nicholasrice @chrisdholt @EisenbergEffect -/packages/tooling/fast-tooling-wasm/ @janechu @nicholasrice @chrisdholt @EisenbergEffect -/packages/tooling/fast-tooling/ @janechu @nicholasrice @chrisdholt @EisenbergEffect - -# Utilities -/packages/utilities/fast-animation/ @nicholasrice @chrisdholt -/packages/utilities/fast-colors/ @nicholasrice @chrisdholt -/packages/utilities/fast-eslint-rules/ @nicholasrice @janechu @chrisdholt -/packages/utilities/fast-web-utilities/ @janechu @chrisdholt @nicholasrice - -# Web components -/packages/web-components/fast-element/ @EisenbergEffect @chrisdholt @janechu @nicholasrice -/packages/web-components/fast-components/ @EisenbergEffect @chrisdholt @janechu @nicholasrice +* @chrisdholt @janechu @radium-v diff --git a/.github/ISSUE_TEMPLATE/bug-report.md b/.github/ISSUE_TEMPLATE/bug-report.md new file mode 100644 index 00000000000..ffa31d8d315 --- /dev/null +++ b/.github/ISSUE_TEMPLATE/bug-report.md @@ -0,0 +1,48 @@ +--- +name: 'πŸ› Bug Report' +about: Did FAST not work as expected? +title: "fix: [what is the issue?] in [where is the issue?]" +labels: 'status:triage' +--- + + + +# πŸ› Bug Report + + + +## πŸ’» Repro or Code Sample + + + +## πŸ€” Expected Behavior + + + +## 😯 Current Behavior + + + + + +## πŸ’ Possible Solution + + + + +## πŸ”¦ Context + + + + +## 🌍 Your Environment + + + +* OS & Device: [e.g. MacOS, iOS, Windows, Linux] on [iPhone 7, PC] +* Browser [e.g. Microsoft Edge, Google Chrome, Apple Safari, Mozilla FireFox] +* Version [e.g. 1.8.0] \ No newline at end of file diff --git a/.github/ISSUE_TEMPLATE/documentation.md b/.github/ISSUE_TEMPLATE/documentation.md new file mode 100644 index 00000000000..674a57ff658 --- /dev/null +++ b/.github/ISSUE_TEMPLATE/documentation.md @@ -0,0 +1,20 @@ +--- +name: πŸ“š Documentation +about: Find an inaccuracy in the documentation or something missing? +title: "docs: fix/add [what] to/in [where]" +labels: 'status:triage' +--- + + + +# πŸ™‹ Documentation Request + + + +## πŸ’ Possible Solution + + \ No newline at end of file diff --git a/.github/ISSUE_TEMPLATE/feature-request.md b/.github/ISSUE_TEMPLATE/feature-request.md new file mode 100644 index 00000000000..86f93353f01 --- /dev/null +++ b/.github/ISSUE_TEMPLATE/feature-request.md @@ -0,0 +1,40 @@ +--- +name: πŸ™‹ Feature Request +about: Want us to add something to FAST? +title: "feat: add [what] to/in [where]" +labels: 'status:triage' +--- + + + +# πŸ™‹ Feature Request + + + +## πŸ€” Expected Behavior + + + +## 😯 Current Behavior + + + +## πŸ’ Possible Solution + + + + +## πŸ”¦ Context + + + + + +## πŸ’» Examples + + + \ No newline at end of file diff --git a/.github/ISSUE_TEMPLATE/report-a-bug.md b/.github/ISSUE_TEMPLATE/report-a-bug.md deleted file mode 100644 index 07a0c5a8944..00000000000 --- a/.github/ISSUE_TEMPLATE/report-a-bug.md +++ /dev/null @@ -1,31 +0,0 @@ ---- -name: Report a bug -about: Report a bug to help us improve FAST. -title: "[what is the issue?] in [where is the issue?]" -labels: 'status:triage' -assignees: '' - ---- - -**Describe the bug; what happened?** - -**What are the steps to reproduce the issue?** - -Example: - -1. Go to '...' -2. Click on '....' -3. Scroll down to '....' -4. See error - -**What behavior did you expect?** - -**If applicable, provide screenshots:** - -**In what environment did you see the issue?** - -* OS & Device: [e.g. MacOS, iOS, Windows, Linux] on [iPhone 7, PC] -* Browser [e.g. Microsoft Edge, Google Chrome, Apple Safari, Mozilla FireFox] -* Version [e.g. 1.8.0] - -**Is there any additional context?** diff --git a/.github/ISSUE_TEMPLATE/request-a-feature.md b/.github/ISSUE_TEMPLATE/request-a-feature.md deleted file mode 100644 index 2c550fb78de..00000000000 --- a/.github/ISSUE_TEMPLATE/request-a-feature.md +++ /dev/null @@ -1,20 +0,0 @@ ---- -name: Request a feature -about: Suggest a feature or share an idea for FAST. -title: Add [what] to/in [where] -labels: 'status:triage' -assignees: '' - ---- - -**What feature are you requesting?** - -**What would be the benefit of adding this feature?** - -**What solution would be ideal for you?** - -**What alternatives have you considered?** - -**Is there any additional context for your request?** - -**Attach screenshots or images add detail to your request:** diff --git a/.github/ISSUE_TEMPLATE/rfc.md b/.github/ISSUE_TEMPLATE/rfc.md new file mode 100644 index 00000000000..150659d5394 --- /dev/null +++ b/.github/ISSUE_TEMPLATE/rfc.md @@ -0,0 +1,27 @@ +--- +name: πŸ’¬ Request For Comment (RFC) +about: Want comments from the team and community on your proposal? +title: "rfc: add [what] to/in [where]" +labels: 'status:triage' +--- + + + +# πŸ’¬ RFC + + + +## πŸ”¦ Context + + + + + +## πŸ’» Examples + + + \ No newline at end of file diff --git a/.github/pull_request_template.md b/.github/pull_request_template.md index 6add3f9f520..bb2d15c3472 100644 --- a/.github/pull_request_template.md +++ b/.github/pull_request_template.md @@ -1,70 +1,56 @@ - + +Provide a summary of your changes in the title field above. +--> -## Motivation & context +# Pull Request - - +## πŸ“– Description -## Issue type checklist + - +### 🎫 Issues -- [ ] **Chore**: A change that does not impact distributed packages. -- [ ] **Bug fix**: A change that fixes an issue, link to the issue above. -- [ ] **New feature**: A change that adds functionality. + -**Is this a breaking change?** -- [ ] This change causes current functionality to break. +## πŸ‘©β€πŸ’» Reviewer Notes - + - +## πŸ“‘ Test Plan -- [ ] I have added a new component -- [ ] I have modified an existing component -- [ ] I have updated the [definition file](https://github.com/Microsoft/fast/blob/master/packages/web-components/fast-components/CONTRIBUTING.md#definition) -- [ ] I have updated the [configuration file](https://github.com/Microsoft/fast/blob/master/packages/web-components/fast-components/CONTRIBUTING.md#configuration) + + +## βœ… Checklist -## Process & policy checklist +### General - + +- [ ] I have included a change request file using `$ npm run change` - [ ] I have added tests for my changes. - [ ] I have tested my changes. - [ ] I have updated the project documentation to reflect my changes. -- [ ] I have read the [CONTRIBUTING](https://github.com/Microsoft/fast/blob/master/CONTRIBUTING.md) documentation and followed the [standards](https://www.fast.design/docs/community/code-of-conduct/#our-standards) for this project. - - \ No newline at end of file diff --git a/.github/workflows/README.md b/.github/workflows/README.md new file mode 100644 index 00000000000..2d4e445e81a --- /dev/null +++ b/.github/workflows/README.md @@ -0,0 +1,5 @@ +# Testing + +To test workflows, use the GitHub CLI and trigger the workflow from a branch. + +For more information see the [GitHub CLI documentation](https://cli.github.com/manual/gh_workflow_run). \ No newline at end of file diff --git a/.github/workflows/cd-color-stage.yml b/.github/workflows/cd-color-stage.yml deleted file mode 100644 index 2f8f39c8a38..00000000000 --- a/.github/workflows/cd-color-stage.yml +++ /dev/null @@ -1,52 +0,0 @@ -name: CD - Color Explorer - -on: - push: - branches: - - master - -jobs: - build_deploy_linux: - runs-on: ubuntu-latest - - env: - AZURE_WEBAPP_ACTIVE_STAGE_NAME: color-west-app - AZURE_WEBAPP_PASSIVE_STAGE_NAME: color-east-app - AZURE_WEBAPP_BUILD_PATH: sites/fast-color-explorer - AZURE_WEBAPP_DIST_PATH: sites/fast-color-explorer/www - AZURE_WEBAPP_SLOT_NAME: stage - - steps: - - name: Checkout Branch - uses: actions/checkout@master - - - name: Install Lerna - run: yarn global add lerna - - - name: Install package dependencies / prepare workspaces - run: yarn install --frozen-lockfile - - - name: Build & Prepare Web Application - run: | - cd ${{ env.AZURE_WEBAPP_BUILD_PATH }} - yarn build - cp ../site-utilities/statics/server/package.json ../site-utilities/statics/server/server.js www - cd www - npm i - ls -lta - - - name: 'Deploy to Active Azure Region' - uses: azure/webapps-deploy@v2 - with: - publish-profile: ${{ secrets.AZURE_PUBLISH_PROFILE_COLOR_ACTIVE }} - app-name: ${{ env.AZURE_WEBAPP_ACTIVE_STAGE_NAME }} - package: ${{ env.AZURE_WEBAPP_DIST_PATH }} - slot-name: ${{ env.AZURE_WEBAPP_SLOT_NAME }} - - - name: 'Deploy to Passive Azure Region' - uses: azure/webapps-deploy@v2 - with: - publish-profile: ${{ secrets.AZURE_PUBLISH_PROFILE_COLOR_PASSIVE }} - app-name: ${{ env.AZURE_WEBAPP_PASSIVE_STAGE_NAME }} - package: ${{ env.AZURE_WEBAPP_DIST_PATH }} - slot-name: ${{ env.AZURE_WEBAPP_SLOT_NAME }} diff --git a/.github/workflows/cd-create-stage.yml b/.github/workflows/cd-create-stage.yml deleted file mode 100644 index c51dd8e4fac..00000000000 --- a/.github/workflows/cd-create-stage.yml +++ /dev/null @@ -1,52 +0,0 @@ -name: CD - Creator - -on: - push: - branches: - - master - -jobs: - build_deploy_linux: - runs-on: ubuntu-latest - - env: - AZURE_WEBAPP_ACTIVE_STAGE_NAME: create-west-app - AZURE_WEBAPP_PASSIVE_STAGE_NAME: create-east-app - AZURE_WEBAPP_BUILD_PATH: sites/fast-creator - AZURE_WEBAPP_DIST_PATH: sites/fast-creator/www - AZURE_WEBAPP_SLOT_NAME: stage - - steps: - - name: Checkout Branch - uses: actions/checkout@master - - - name: Install Lerna - run: yarn global add lerna - - - name: Install package dependencies / prepare workspaces - run: yarn install --frozen-lockfile - - - name: Build & Prepare Web Application - run: | - cd ${{ env.AZURE_WEBAPP_BUILD_PATH }} - yarn build - cp ../site-utilities/statics/server/package.json ../site-utilities/statics/server/server.js www - cd www - npm i - ls -lta - - - name: 'Deploy to Active Azure Region' - uses: azure/webapps-deploy@v2 - with: - publish-profile: ${{ secrets.AZURE_PUBLISH_PROFILE_CREATE_ACTIVE }} - app-name: ${{ env.AZURE_WEBAPP_ACTIVE_STAGE_NAME }} - package: ${{ env.AZURE_WEBAPP_DIST_PATH }} - slot-name: ${{ env.AZURE_WEBAPP_SLOT_NAME }} - - - name: 'Deploy to Passive Azure Region' - uses: azure/webapps-deploy@v2 - with: - publish-profile: ${{ secrets.AZURE_PUBLISH_PROFILE_CREATE_PASSIVE }} - app-name: ${{ env.AZURE_WEBAPP_PASSIVE_STAGE_NAME }} - package: ${{ env.AZURE_WEBAPP_DIST_PATH }} - slot-name: ${{ env.AZURE_WEBAPP_SLOT_NAME }} diff --git a/.github/workflows/cd-explore-stage.yml b/.github/workflows/cd-explore-stage.yml deleted file mode 100644 index 7b8e7288ae9..00000000000 --- a/.github/workflows/cd-explore-stage.yml +++ /dev/null @@ -1,52 +0,0 @@ -name: CD - Component Explorer - -on: - push: - branches: - - master - -jobs: - build_deploy_linux: - runs-on: ubuntu-latest - - env: - AZURE_WEBAPP_ACTIVE_STAGE_NAME: explore-west-app - AZURE_WEBAPP_PASSIVE_STAGE_NAME: explore-east-app - AZURE_WEBAPP_BUILD_PATH: sites/fast-component-explorer - AZURE_WEBAPP_DIST_PATH: sites/fast-component-explorer/www - AZURE_WEBAPP_SLOT_NAME: stage - - steps: - - name: Checkout Branch - uses: actions/checkout@master - - - name: Install Lerna - run: yarn global add lerna - - - name: Install package dependencies / prepare workspaces - run: yarn install --frozen-lockfile - - - name: Build & Prepare Web Application - run: | - cd ${{ env.AZURE_WEBAPP_BUILD_PATH }} - yarn build:app - cp ../site-utilities/statics/server/package.json ../site-utilities/statics/server/server.js www - cd www - npm i - ls -lta - - - name: 'Deploy to Active Azure Region' - uses: azure/webapps-deploy@v2 - with: - publish-profile: ${{ secrets.AZURE_PUBLISH_PROFILE_EXPLORE_ACTIVE }} - app-name: ${{ env.AZURE_WEBAPP_ACTIVE_STAGE_NAME }} - package: ${{ env.AZURE_WEBAPP_DIST_PATH }} - slot-name: ${{ env.AZURE_WEBAPP_SLOT_NAME }} - - - name: 'Deploy to Passive Azure Region' - uses: azure/webapps-deploy@v2 - with: - publish-profile: ${{ secrets.AZURE_PUBLISH_PROFILE_EXPLORE_PASSIVE }} - app-name: ${{ env.AZURE_WEBAPP_PASSIVE_STAGE_NAME }} - package: ${{ env.AZURE_WEBAPP_DIST_PATH }} - slot-name: ${{ env.AZURE_WEBAPP_SLOT_NAME }} \ No newline at end of file diff --git a/.github/workflows/cd-gh-pages.yml b/.github/workflows/cd-gh-pages.yml new file mode 100644 index 00000000000..05834756ea4 --- /dev/null +++ b/.github/workflows/cd-gh-pages.yml @@ -0,0 +1,62 @@ +name: Deploy GitHub Pages + +on: + workflow_dispatch: + +env: + GITHUB_SERVICE_USER: "Microsoft FAST Builds" + GITHUB_SERVICE_EMAIL: "fastsvc@microsoft.com" + +permissions: + contents: write + +jobs: + build: + runs-on: ubuntu-latest + strategy: + matrix: + node: [22.x] + + steps: + - uses: actions/checkout@v4 + - name: Use Node.js ${{ matrix.node-version }} + uses: actions/setup-node@v4 + with: + node-version: ${{ matrix.node-version }} + fetch-depth: 0 + + - name: Set Git User + run: | + git config --global user.name "${{ env.GITHUB_SERVICE_USER }}" + git config --global user.email "${{ env.GITHUB_SERVICE_EMAIL }}" + + - name: Cache multiple paths + uses: actions/cache@v4 + env: + cache-name: cache-node-modules + with: + path: ~/.npm + key: ${{ runner.os }}-build-${{ env.cache-name }}-${{ hashFiles('**/package-lock.json') }} + restore-keys: | + ${{ runner.os }}-build-${{ env.cache-name }}- + ${{ runner.os }}-build- + ${{ runner.os }}- + + - name: Install package dependencies + run: npm ci + + - name: Build workspaces + run: npm run build + + - name: Build GitHub Pages + run: npm run build:gh-pages + + - name: Deploy GitHub Pages + uses: JamesIves/github-pages-deploy-action@v4 + with: + token: ${{ secrets.GH_TOKEN }} + branch: gh-pages # The branch the action should deploy to. + folder: sites/website/build # The folder the action should deploy. + target-folder: docs # The folder on the branch to deploy to. + clean: true # Remove old files to clean up unique hash files. + single-commit: true # Only use a single commit to keep the branch free from git history. diff --git a/.github/workflows/cd-static-cdn.yml b/.github/workflows/cd-static-cdn.yml deleted file mode 100644 index 7334e610484..00000000000 --- a/.github/workflows/cd-static-cdn.yml +++ /dev/null @@ -1,22 +0,0 @@ -name: CD - Static Assets - -on: - push: - branches: - - master - -jobs: - deploy_linux: - runs-on: ubuntu-latest - - steps: - - name: Checkout Branch - uses: actions/checkout@master - - - name: Upload static assets to CDN - uses: lauchacarro/Azure-Storage-Action@master - with: - folder: 'sites/site-utilities/statics/assets' - connection-string: ${{ secrets.AZURE_CONNECTION_STRING_STORAGE }} - public-access-policy: Blob - blob-container-name: 'assets' \ No newline at end of file diff --git a/.github/workflows/cd-www-stage.yml b/.github/workflows/cd-www-stage.yml deleted file mode 100644 index 2cfb25a968b..00000000000 --- a/.github/workflows/cd-www-stage.yml +++ /dev/null @@ -1,52 +0,0 @@ -name: CD - FAST -on: - push: - branches: - - master - -jobs: - build_deploy_linux: - runs-on: ubuntu-latest - - env: - AZURE_WEBAPP_ACTIVE_STAGE_NAME: www-west-app - AZURE_WEBAPP_PASSIVE_STAGE_NAME: www-east-app - AZURE_WEBAPP_BUILD_PATH: sites/website - AZURE_WEBAPP_DIST_PATH: sites/website/build - AZURE_WEBAPP_SLOT_NAME: stage - - steps: - - name: Checkout Branch - uses: actions/checkout@master - - - name: Install Lerna - run: yarn global add lerna - - - name: Install package dependencies / prepare workspaces - run: yarn install --frozen-lockfile - - - name: Build & Prepare Web Application - run: | - cd ${{ env.AZURE_WEBAPP_BUILD_PATH }} - npm i - yarn build - cp ../site-utilities/statics/server/package.json ../site-utilities/statics/server/server.js build - cd build - npm i - ls -lta - - - name: 'Deploy to Active Azure Region' - uses: azure/webapps-deploy@v2 - with: - publish-profile: ${{ secrets.AZURE_PUBLISH_PROFILE_WWW_ACTIVE }} - app-name: ${{ env.AZURE_WEBAPP_ACTIVE_STAGE_NAME }} - package: ${{ env.AZURE_WEBAPP_DIST_PATH }} - slot-name: ${{ env.AZURE_WEBAPP_SLOT_NAME }} - - - name: 'Deploy to Passive Azure Region' - uses: azure/webapps-deploy@v2 - with: - publish-profile: ${{ secrets.AZURE_PUBLISH_PROFILE_WWW_PASSIVE }} - app-name: ${{ env.AZURE_WEBAPP_PASSIVE_STAGE_NAME }} - package: ${{ env.AZURE_WEBAPP_DIST_PATH }} - slot-name: ${{ env.AZURE_WEBAPP_SLOT_NAME }} \ No newline at end of file diff --git a/.github/workflows/ci-daily.yml b/.github/workflows/ci-daily.yml deleted file mode 100644 index b41eafd127d..00000000000 --- a/.github/workflows/ci-daily.yml +++ /dev/null @@ -1,65 +0,0 @@ -name: CI - FAST - -on: - push: - branches: - - master - - releases/* - pull_request: - branches: - - master - - releases/* - - features/* - - feature/* - -jobs: - build_linux: - runs-on: ubuntu-latest - - steps: - - uses: actions/checkout@v2 - - - name: gcc - run: | - gcc-8 --version - shell: bash - - - name: Add or Update packages - run: sudo yarn global add lerna@3.18.2 - - - name: Get yarn cache directory path - id: yarn-cache-dir-path - run: echo '::set-output name=dir::$(yarn cache dir)' - - - name: Set up node_modules cache - uses: actions/cache@v1.1.2 - id: yarn-cache - with: - path: ${{ steps.yarn-cache-dir-path.outputs.dir }} - key: ${{ runner.os }}-yarn-${{ hashFiles('**/yarn.lock') }} - restore-keys: | - ${{ runner.os }}-yarn- - - - name: Install package dependencies / prepare workspaces - run: yarn install --frozen-lockfile - - - name: Testing Prettier format - run: lerna run prettier:diff - - - name: Testing unit tests - run: lerna run test --stream - - - name: Collect and upload code coverage to Code Climate - uses: paambaati/codeclimate-action@v2.6.0 - env: - CC_TEST_REPORTER_ID: 08a773cb4ea5811add5a45e12873e5cd2634c005568705cc37abfd5217617a32 - with: - coverageCommand: lerna run coverage - coverageLocations: | - ${{github.workspace}}/packages/tooling/fast-tooling/coverage/lcov.info:lcov - ${{github.workspace}}/packages/tooling/fast-tooling-react/coverage/lcov.info:lcov - ${{github.workspace}}/packages/utilities/fast-animation/coverage/lcov.info:lcov - ${{github.workspace}}/packages/utilities/fast-colors/coverage/lcov.info:lcov - ${{github.workspace}}/packages/utilities/fast-web-utilities/coverage/lcov.info:lcov - ${{github.workspace}}/sites/fast-component-explorer/coverage/lcov.info:lcov - debug: false \ No newline at end of file diff --git a/.github/workflows/ci-validate-platforms.yml b/.github/workflows/ci-validate-platforms.yml new file mode 100644 index 00000000000..73aa4feddaf --- /dev/null +++ b/.github/workflows/ci-validate-platforms.yml @@ -0,0 +1,68 @@ +name: Validate Platforms/Browsers + +on: + workflow_dispatch: + push: + branches: + - main + + pull_request: + branches: + - main + + schedule: + - cron: 0 7 * * 3 + +jobs: + cross-platform_cross-browser: + runs-on: ${{ matrix.os }} + + strategy: + fail-fast: true + matrix: + os: [ubuntu-latest, windows-latest, macos-latest] + + env: + PLAYWRIGHT_BROWSERS_PATH: 0 + + steps: + - name: Set git to use LF + if: ${{ matrix.os == 'windows-latest' }} + run: | + git config --global core.autocrlf false + git config --global core.eol lf + + - name: Checkout Branch + uses: actions/checkout@v2 + + - if: ${{ github.event_name == 'pull_request' }} + run: | + git fetch --no-tags --prune --depth=1 origin +refs/heads/main:refs/remotes/origin/main + + - name: Cache multiple paths + uses: actions/cache@v4 + env: + cache-name: cache-node-modules + with: + path: ~/.npm + key: ${{ runner.os }}-build-${{ env.cache-name }}-${{ hashFiles('**/package-lock.json') }} + restore-keys: | + ${{ runner.os }}-build-${{ env.cache-name }}- + ${{ runner.os }}-build- + ${{ runner.os }}- + + - name: Install package dependencies + run: npm ci + + - name: Test Prettier format + run: npm run format:check + + - name: Build workspaces + run: npm run build + + - name: Install playwright dependencies and browsers + run: | + npx playwright install + + - name: Run tests in all Packages + run: npm run test diff --git a/.github/workflows/ci-validate-pr.yml b/.github/workflows/ci-validate-pr.yml new file mode 100644 index 00000000000..4f061f8ab6d --- /dev/null +++ b/.github/workflows/ci-validate-pr.yml @@ -0,0 +1,58 @@ +name: Validate PRs + +on: + workflow_dispatch: + push: + branches: + - main + - releases/* + pull_request: + branches: + - main + - releases/* + - features/* + +jobs: + build_linux: + runs-on: ubuntu-latest + env: + PLAYWRIGHT_BROWSERS_PATH: 0 + + steps: + - uses: actions/checkout@v4 + with: + fetch-depth: 0 + + - name: Cache multiple paths + uses: actions/cache@v4 + env: + cache-name: cache-node-modules + with: + path: ~/.npm + key: ${{ runner.os }}-build-${{ env.cache-name }}-${{ hashFiles('**/package-lock.json') }} + restore-keys: | + ${{ runner.os }}-build-${{ env.cache-name }}- + ${{ runner.os }}-build- + ${{ runner.os }}- + + - name: Install package dependencies + run: npm ci + + - name: Check for the presence of changed files inside ./change + run: npm run checkchange + + - name: Testing Prettier format + run: npm run format:check + + - name: Build workspaces + run: npm run build + + - name: Install playwright dependencies and browsers + run: | + npx playwright install + + - name: Testing unit tests + run: npm run test + + - name: Testing final validation + run: npm run test:validation diff --git a/.github/workflows/ci-weekly.yml b/.github/workflows/ci-weekly.yml deleted file mode 100644 index 3fe2b40009e..00000000000 --- a/.github/workflows/ci-weekly.yml +++ /dev/null @@ -1,87 +0,0 @@ -name: CI - FAST Validation - -on: - schedule: - - cron: 0 7 * * 3 - - -jobs: - build_windows: - name: Validate on Windows - runs-on: windows-latest - - steps: - - uses: actions/checkout@v2 - - - name: gcc - run: | - gcc-8 --version - shell: bash - - - name: Setup Node.js environment - uses: actions/setup-node@v2.1.0 - with: - node-version: '10' - - - name: Install Lerna - run: npm i -g lerna - - - name: Install package dependencies / prepare workspaces - env: - CHILD_CONCURRENCY: 1 - run: | - yarn install --frozen-lockfile - - - name: Ensure Prettier formatting - run: lerna run prettier:diff - - - name: Execute unit tests - run: lerna run test --stream - - - build_macos: - name: Validate on MacOS - - runs-on: macos-latest - - steps: - - uses: actions/checkout@v2 - - - name: Setup Node.js environment - uses: actions/setup-node@v2.1.0 - with: - node-version: '10' - - - name: Install Lerna - run: sudo yarn global add lerna - - - name: Install package dependencies / prepare workspaces - run: yarn install --frozen-lockfile - - - name: Ensure Prettier formatting - run: lerna run prettier:diff - - - name: Execute unit tests - run: lerna run test --stream - - code_scan: - name: Validate Security - - runs-on: ubuntu-latest - - steps: - - uses: actions/checkout@v2 - with: - fetch-depth: 2 - - - run: git checkout HEAD^2 - if: ${{ github.event_name == 'pull_request' }} - - - name: Initialize CodeQL - uses: github/codeql-action/init@v1 - - - name: Autobuild - uses: github/codeql-action/autobuild@v1 - - - name: Perform CodeQL Analysis - uses: github/codeql-action/analyze@v1 \ No newline at end of file diff --git a/.github/workflows/pr.yml b/.github/workflows/pr.yml deleted file mode 100644 index 1578cf57932..00000000000 --- a/.github/workflows/pr.yml +++ /dev/null @@ -1,17 +0,0 @@ -name: "PR - FAST" -on: - pull_request: - types: - - opened - - reopened - - edited - - synchronize - -jobs: - lint_title: - runs-on: ubuntu-latest - - steps: - - uses: amannn/action-semantic-pull-request@v1.2.0 - env: - GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} diff --git a/.github/workflows/testing/README.md b/.github/workflows/testing/README.md deleted file mode 100644 index 5aa679738af..00000000000 --- a/.github/workflows/testing/README.md +++ /dev/null @@ -1,63 +0,0 @@ -# Local testing of GitHub Actions -Leverage the knowledge from https://github.com/nektos/act for detailed instructions. - -## Install -### 1. Install Docker -Required to run GitHub Actions on VMs. Choose your preferred Docker setup https://docs.docker.com/get-docker/. - -### 2. Install Nektos -Required to run GitHub Actions locally. - -```bash -brew install nektos/tap/act -``` - -### 3. Install Azure CLI -Required to integrate GitHub Actions and Azure. - -```bash -azure login -``` - -## Configure -1. The `.actrc` file contains the default configuration and run methods. -2. Run this Bash script `ci-act-event.sh` to dynamically generate the required configuration file for Act. Two questions will be asked to collect the local git branch name and GitHub event. An example might look like `.github/workflows/testing/push.json` where "push" is the github.event to trigger a GitHub Action against the branch named inside that same file. This file is `.gitignored` so it will need regenerated for testing. - -```bash -cd .github/workflows/testing -bash ci-act-event.sh -``` - -A new file `{some-name}.json` will be generated inside `/testing/`. This is the local git branch that `Act` will run. - -Run the event from the `/testing/*` folder as indicated with `-W` or `--workflows` arguments. - -```bash -$ act -e `.github/workflows/testing/${github_event}.json` -W "./.github/workflows/testing/" -``` - -## Test -`./.github/workflows/testing/ci-daily-local.yml` is used to test locally CI settings. - -Run this command from root -```bash -$ act -j build_local_linux -e "./.github/workflows/testing/${github_event}.json" -W "./.github/workflows/testing/" -``` -## Cleanup -When installing packages on docker instances, if versions change, it's important to kill the docker instance and rebuild. - -Determine what instances are running. -```bash -$ docker ps -``` - -Copy and paste the "CONTAINER ID" as the argument of `kill`. -```bash -$ docker kill 2ecf895e7be3 -``` - -Remove the image. -```bash -$ docker rm 2ecf895e7be3 -``` - diff --git a/.github/workflows/testing/ci-act-event.sh b/.github/workflows/testing/ci-act-event.sh deleted file mode 100644 index e1115bf0ccf..00000000000 --- a/.github/workflows/testing/ci-act-event.sh +++ /dev/null @@ -1,28 +0,0 @@ -#!/bin/bash - -echo " ------------------------------------------------------------------------------------------------ " -echo "| This script will dynamically create an event.json file for use by Nektos/Act in testing GitHub |" -echo "| Actions locally. |" -echo " -------------------------------------------------------------------------------------------------" - -# Ask for Branch Name -echo -n "Enter git branch name? " -read branch_name - -# Ask for Event Type -echo -n "Enter the GitHub Event to trigger the GitHub Action? " -read github_event - -# Combine user inputs into the json template -# Set contents of the file to be overwritten -echo '{ - "push": { - "head": { - "ref": "'$branch_name'" - }, - "base": { - "ref": "'$branch_name'" - } - } - }' >& $github_event.json - diff --git a/.github/workflows/testing/ci-daily-local.yml b/.github/workflows/testing/ci-daily-local.yml deleted file mode 100644 index d5bc292cf95..00000000000 --- a/.github/workflows/testing/ci-daily-local.yml +++ /dev/null @@ -1,44 +0,0 @@ -name: CI - FAST Local Testing - -on: - push: - branches: - - users/* - -jobs: - build_local_linux: - runs-on: ubuntu-latest - - steps: - - uses: actions/checkout@v2 - - - name: Add/Update packages - run: | - sudo apt-get update - sudo apt-get install yarn - sudo yarn global upgrade typescript - sudo yarn global add lerna - - - name: Install package dependencies / prepare workspaces - run: yarn install --frozen-lockfile - - - name: Testing Prettier format - run: lerna run prettier:diff - - - name: Testing units - run: lerna run test --stream - - - name: Collect and upload code coverage to Code Climate - uses: paambaati/codeclimate-action@v2.6.0 - env: - CC_TEST_REPORTER_ID: 08a773cb4ea5811add5a45e12873e5cd2634c005568705cc37abfd5217617a32 - with: - coverageCommand: lerna run coverage - coverageLocations: | - ${{github.workspace}}/packages/tooling/fast-tooling/coverage/lcov.info:lcov - ${{github.workspace}}/packages/tooling/fast-tooling-react/coverage/lcov.info:lcov - ${{github.workspace}}/packages/utilities/fast-animation/coverage/lcov.info:lcov - ${{github.workspace}}/packages/utilities/fast-colors/coverage/lcov.info:lcov - ${{github.workspace}}/packages/utilities/fast-web-utilities/coverage/lcov.info:lcov - ${{github.workspace}}/sites/fast-component-explorer/coverage/lcov.info:lcov - debug: true \ No newline at end of file diff --git a/.gitignore b/.gitignore index d664984b3a8..5badc7efbb9 100644 --- a/.gitignore +++ b/.gitignore @@ -2,8 +2,6 @@ logs *.log npm-debug.log* -yarn-debug.log* -yarn-error.log* # Coverage directory used by tools like istanbul coverage @@ -21,45 +19,59 @@ typings/ # Optional eslint cache .eslintcache -# Yarn Integrity file -.yarn-integrity - # dotenv environment variables file .env -# Ignore distribution directory +# Ignore distribution directory dist/ # Ignore build www directories www/ storybook-static -#Ignore Mac .DS_Store +# Ignore Mac .DS_Store .DS_Store -#Ignore VSCode -.vscode/ -.vs/ +#Ignore VSCode in Root +.vscode/* +!.vscode/settings.json +!.vscode/tasks.json +!.vscode/launch.json +!.vscode/extensions.json +*.code-workspace + +# Local History for Visual Studio Code +.history/ + +# Stores VSCode versions used for testing VSCode extensions +.vscode-test + +# Ignore Intellij IDEA +.idea # tmp directories .tmp/ - -# npm package-locks -package-lock.json +temp/ # Docusaurus files to ignore sites/website/build/ sites/website/docs/ sites/website/src/docs/api/ -sites/website/yarn.lock sites/website/node_modules sites/website/i18n/ -# Docusaurus package readme's -docs/en/packages/*/README.md - -# TypeDoc generated subsites -docs/en/packages/*/api/ - # GitHub Actions Local Testing .github/workflows/testing/*.json + +# Ignore Build Artefacts +bin/ +obj/ + +# Tensile performance test results +.tensile + +# Test results +test-results/ + +# Pack directory +publish_artifacts/ diff --git a/.npmrc b/.npmrc index 43c97e719a5..c2807d1be96 100644 --- a/.npmrc +++ b/.npmrc @@ -1 +1,3 @@ -package-lock=false +//registry.npmjs.org/:_authToken=$NPM_TOKEN +@microsoft:registry=https://registry.npmjs.org/ +always-auth=true diff --git a/.prettierignore b/.prettierignore index 1b428b6629b..5f93efd5643 100644 --- a/.prettierignore +++ b/.prettierignore @@ -1 +1,19 @@ -packages/web-components/fast-components/src/default-palette.ts +*.spec.ts +!*.pw.spec.ts +*.spec.tsx +**/__tests__ +**/__test__ +**/.tmp +**/bootstrap +**/coverage +**/dist +**/temp +default-palette.ts +*.md +*.mdx +*.js +*.cjs +*.json +*.html +*.webapp +*.yml diff --git a/.prettierrc b/.prettierrc index 2bc74dd37dd..9698214d8fa 100644 --- a/.prettierrc +++ b/.prettierrc @@ -6,7 +6,7 @@ "singleQuote": false, "trailingComma": "es5", "bracketSpacing": true, - "jsxBracketSameLine": false, "arrowParens": "avoid", - "htmlWhitespaceSensitivity": "ignore" -} \ No newline at end of file + "htmlWhitespaceSensitivity": "ignore", + "endOfLine": "auto" +} diff --git a/.vscode/extensions.json b/.vscode/extensions.json new file mode 100644 index 00000000000..4e4f7afa343 --- /dev/null +++ b/.vscode/extensions.json @@ -0,0 +1,11 @@ +{ + "recommendations": [ + "bierner.github-markdown-preview", + "bierner.jsdoc-markdown-highlighting", + "dbaeumer.vscode-eslint", + "ghmcadams.lintlens", + "ms-fast.fast-tagged-templates", + "rvest.vs-code-prettier-eslint", + "sidneys1.gitconfig" + ] +} diff --git a/.vscode/settings.json b/.vscode/settings.json new file mode 100644 index 00000000000..02b830b0c3c --- /dev/null +++ b/.vscode/settings.json @@ -0,0 +1,33 @@ +{ + "[json]": { + "files.insertFinalNewline": false + }, + "[markdown]": { + "editor.quickSuggestions": { + "other": "off" + }, + "files.insertFinalNewline": false, + "files.trimTrailingWhitespace": false + }, + "[typescript]": { + "editor.tabSize": 4 + }, + "editor.trimAutoWhitespace": true, + "eslint.codeActionsOnSave.mode": "problems", + "eslint.lintTask.enable": true, + "eslint.validate": [ + "typescript" + ], + "files.eol": "\n", + "files.insertFinalNewline": true, + "files.trimFinalNewlines": true, + "files.trimTrailingWhitespace": true, + "javascript.format.enable": false, + "javascript.format.insertSpaceAfterFunctionKeywordForAnonymousFunctions": false, + "js/ts.implicitProjectConfig.experimentalDecorators": true, + "npm.packageManager": "npm", + "typescript.enablePromptUseWorkspaceTsdk": true, + "typescript.format.enable": false, + "typescript.preferences.quoteStyle": "double", + "typescript.tsdk": "node_modules/typescript/lib" +} diff --git a/BRANCH_GUIDE.md b/BRANCH_GUIDE.md new file mode 100644 index 00000000000..a52a6a7cd2d --- /dev/null +++ b/BRANCH_GUIDE.md @@ -0,0 +1,19 @@ +# Branch guide + +This is the branch guide for the FAST repository. When contributing to this project please follow the standards defined in this guide. + +## Default + +The `main` branch is the default branch. It is used for all releases pinned to the current major version. Most pull requests should be merged directly into this branch so that they can be automatically checked for publishing. + +## Features + +If a large feature or a breaking change has been defined, a feature branch may be created. To be significant enough work to require a feature branch, the work must comprise of more than one pull request. The feature branch should follow the naming convention `features/*`. This will allow GitHub workflows, including the build gate, to trigger on any pull request opened against the feature branch. + +### Changelog + +Due to the default behavior of beachball (the package publishing utility used in this repository), the `beachball.config.js` which defaults to checking for changes against the default branch must be updated to point to the feature branch, and if necessary, allowed to add major changes. The branch creation should start by updating `beachball.config.js`, to do this refer to the [beachball options](https://github.com/microsoft/beachball/blob/master/docs/overview/configuration.md#options). This change must be reverted before inclusion to the default branch. + +### Merging + +When merging a feature branch to the default branch, changes should not be squashed to preserve history. This will require a special action from someone with the necessary security privileges to change the settings in the repository for pull requests to merge without squashing. The user performing this action will, after merging the feature branch in, need to change this setting back. \ No newline at end of file diff --git a/CODE_OF_CONDUCT.md b/CODE_OF_CONDUCT.md index a22238d717d..8d81cc6a2db 100644 --- a/CODE_OF_CONDUCT.md +++ b/CODE_OF_CONDUCT.md @@ -2,7 +2,7 @@ ## Our Pledge -In the interest of fostering an open and welcoming environment, we as contributors and maintainers pledge to making participation in our project and our community a harassment-free experience for everyone, regardless of age, body size, disability, ethnicity, gender identity and expression, level of experience, nationality, personal appearance, race, religion, or sexual identity and orientation. +In the interest of fostering an open and welcoming environment, we as contributors and maintainers pledge to make participation in our project and our community a harassment-free experience for everyone, regardless of age, body size, disability, ethnicity, gender identity and expression, level of experience, nationality, personal appearance, race, religion, or sexual identity and orientation. ## Our Standards @@ -19,7 +19,7 @@ Examples of unacceptable behavior by participants include: * The use of sexualized language or imagery and unwelcome sexual attention or advances * Trolling, insulting/derogatory comments, and personal or political attacks * Public or private harassment -* Publishing others' private information, such as a physical or electronic address, without explicit permission +* Publishing other's private information, such as a physical or electronic address, without explicit permission * Other conduct which could reasonably be considered inappropriate in a professional setting ## Our Responsibilities @@ -40,7 +40,7 @@ Project maintainers who do not follow or enforce the Code of Conduct in good fai ## Attribution -This Code of Conduct is adapted from the [Contributor Covenant][homepage], version 1.4, available at [http://contributor-covenant.org/version/1/4][version] +This Code of Conduct is adapted from the [Contributor Covenant][homepage], version 1.4, available at [https://contributor-covenant.org/version/1/4][version] -[homepage]: http://contributor-covenant.org -[version]: http://contributor-covenant.org/version/1/4/ +[homepage]: https://contributor-covenant.org +[version]: https://contributor-covenant.org/version/1/4/ diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index c7ec43c4069..682a3f867ed 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -4,28 +4,12 @@ ### Machine setup -To work with the FAST [monorepo](https://en.wikipedia.org/wiki/Monorepo) you'll need Git, Node.js, Yarn, and Lerna setup on your machine. +To work with the FAST [monorepo](https://en.wikipedia.org/wiki/Monorepo) you'll need Git, Node.js, and Npm setup on your machine. FAST uses Git as its source control system. If you haven't already installed it, you can download it [here](https://git-scm.com/downloads) or if you prefer a GUI-based approach, try [GitHub Desktop](https://desktop.github.com/). Once Git is installed, you'll also need Node.js, which FAST uses as its JavaScript runtime, enabling its build and test scripts. Node.js instructions and downloads for your preferred OS can be found [here](https://nodejs.org/en/). -Because the FAST repository is structured as a monorepo, we'll need a couple of tools to manage that. The first is Yarn, which can be installed by executing the following command at the terminal: - -```shell -npm install -g yarn -``` - -The second tool you'll need is Lerna, which can be installed with this command: - -```bash -yarn global add lerna -``` - -:::important -The above steps are a one-time setup for your machine and do not need to be repeated after the initial configuration. -::: - ### Cloning the repository Now that your machine is setup, you can clone the FAST repository. Open a terminal and run this command: @@ -44,30 +28,21 @@ git clone git@github.com:microsoft/fast.git From within the `fast` folder where you've cloned the repo, install all package dependencies and build all workspaces (local dependencies) with this command: ```bash -yarn +npm ci ``` After the initial install, you can re-build all workspaces in the future with: ```bash -lerna run prepare +npm run build ``` -### Developing in `fast-components` -If you're interested in contributing changes to the `fast-component` design system start by navigating to the `fast-components` directory and starting the Storybook local server there. - -```bash -cd packages/web-components/fast-components -yarn start -``` -Storybook will automatically open in a browser window at `localhost:6006`. - ### Testing To run all tests for all packages, use the following command: ```bash -lerna run test +npm run test ``` This command can also be run from within individual package folders to execute only tests from that package. @@ -78,15 +53,51 @@ Packages are located within the `packages` folder of the repository. Each packag ### Submitting a pull request -If you'd like to contribute by fixing a bug, implementing a feature, or even correcting typos in our documentation, you'll want to submit a pull request. Before submitting a pull request, be sure to [rebase](https://www.atlassian.com/git/tutorials/merging-vs-rebasing) your branch from master. Do not use ``git merge`` or the *merge* button provided by GitHub. +If you'd like to contribute by fixing a bug, implementing a feature, or even correcting typos in our documentation, you'll want to submit a pull request. Before submitting a pull request, be sure to [rebase](https://www.atlassian.com/git/tutorials/merging-vs-rebasing) your branch with the default branch or use the *merge* button provided by GitHub. + +:::note +For additional details on branch management, read the [branch guide](./BRANCH_GUIDE.md) documentation. +::: + +#### Change Files + +Any pull request which includes changes within the `packages/*` directory requires a corresponding change file. Before pushing your changes to create a pull request, be sure you have included the necessary change file(s). To generate a change file, run `npm run change` in the root of the repository. The generated file will be checked into the repo automatically for you as part of the process. + +:::note +When working across feature branches, you'll need to target the branch using the following command: `npm run change --branch origin/{branch-name}`. +::: + +**Example: Generated change file:** +```json +{ + "type": "minor", + "comment": "add fancy new feature to FASTElement", + "packageName": "@microsoft/fast-element", + "email": "name@example.com", + "dependentChangeType": "minor", + "date": "2021-03-01T19:10:06.323Z" +} +``` + +Running `npm run change` will walk you through a CLI process for generating change files. The process will walk you through selecting the type of change as well as ask you to provide a description of any changes. As a convenience, the utility looks to provide recent commit messages for use in the description. *For changes that do not affect the published package(s), please use "none" when selecting the change type*. + +More information on the change process and change types can be found on the [Beachball website](https://microsoft.github.io/beachball/cli/change.html#change). + +:::note +If you are addressing multiple issues which are unrelated, consider either doing multiple pull requests, or generating separate change files to ensure accurate generation of changelogs and versioning of packages. +::: + +:::note +If you are finding that your changes are either breaking changes or require multiple pull requests, open a [discussion](https://github.com/microsoft/fast/discussions) to discuss this. +::: ### Merging a pull request -If you are merging a pull request, be sure to use the pull request title as the commit title. The title should follow the [conventional commit guidelines](https://www.conventionalcommits.org/). It is recommended that if you are merging in pull requests regularly that you add a browser extension that will auto-correct the title for you. A few that should do this are [Refined GitHub](https://github.com/sindresorhus/refined-github) and [Squashed Merge Message](https://github.com/zachwhaley/squashed-merge-message). +If you are merging a pull request, be sure to use the pull request title as the commit title. The title should follow the [conventional commit guidelines](https://www.conventionalcommits.org/). ### Documenting breaking changes -Make sure to document the migration strategy in a `MIGRATION.md` file in the package(s) that has breaking changes, eg. `packages/fast-components-styles-msft/MIGRATION.md`. +Make sure to document the migration strategy in a `MIGRATION.md` file in the package(s) that has breaking changes, eg. `packages/fast-element/MIGRATION.md`. Example of how to format `MIGRATION.md`: @@ -99,6 +110,12 @@ Example of how to format `MIGRATION.md`: - `Bat` has been updated to use the new API [`BatConfig`](link/to/api). ``` +### Recommended Settings for Visual Studio Code + +You can use any code editor you like when working with the FAST monorepo. One of our favorites is [Visual Studio Code](https://code.visualstudio.com/). VS Code has great autocomplete support for TypeScript and JavaScript APIs, as well as a rich ecosystem of plugins. + +Default VS Code settings for this project are configured as [Workspace settings](https://code.visualstudio.com/docs/getstarted/settings) in the `.vscode` directory. These settings override user settings for the workspace and are configured to ensure consistent code formatting across different environments. We also include a list of [Workspace recommended extensions](https://code.visualstudio.com/docs/editor/extension-marketplace#_workspace-recommended-extensions) for VS Code for syntax highlighting and code linting. + ## Contribution policy A β€œContribution” is work voluntarily submitted to a project. This submitted work can include code, documentation, design, answering questions, or submitting and triaging issues. @@ -109,7 +126,7 @@ When you submit a pull request, a CLA-bot automatically determines if you need t ## Guiding principle -Owners, the steering committee, collaborators, code owners, and contributors work in concert with one another on behalf of the FAST community and prioritize the communities interests over their own. +Owners, the steering committee, collaborators, code owners, and contributors work in concert with one another on behalf of the FAST community and prioritize the community's interests over their own. The development, release, and work management processes must reflect this principle. Accepting contributions to the project requires a review by collaborators. @@ -121,15 +138,23 @@ The development, release, and work management processes must reflect this princi ### Steering committee -*Steering committee* members are key *collaborators* who have demonstrated design or technical expertise critical to the driving the FAST project and community forward. +*Steering committee* members are key *collaborators* who have demonstrated design or technical expertise critical to driving the FAST project and community forward. + +* Aaron Wentzel +* Brian Heston +* Chris Holt +* Jane Chu +* Jason Falk +* Nicholas Rice +* Rob Eisenberg ### Collaborators -*Collaborators* have write access and have an active and sustained impact on the project and participate in triaging issues, reviewing code, mentoring, and working to improve the architectural quality. +*Collaborators* have write access and have an active and sustained impact on the project and participate in triaging issues, reviewing code, mentoring, and working to improve the architectural quality. ### Code owners -As subject matter experts, *code owners* approve pull requests on the packages they own. There is a required minimum of one code owner for each package. *Code owners* are listed in [CODEOWNERS](https://github.com/microsoft/fast/blob/master/.github/CODEOWNERS). +As subject matter experts, *code owners* approve pull requests on the packages they own. There is a required minimum of one code owner for each package. *Code owners* are listed in [CODEOWNERS](https://github.com/microsoft/fast/blob/main/.github/CODEOWNERS). ### Contributors @@ -137,28 +162,35 @@ As subject matter experts, *code owners* approve pull requests on the packages t ### Nominations & appointments -* To become a *contributor*, a community member must have a pull request approved and merged into the FAST project master branch. -* To become a *collaborator*, a *contributor* will petition the *steering committee* who will approve or deny the request. -* To become a *code owner*, a *collaborator* will be (a) nominated by a *steering committee* member or (b) petition the *steering committee* who will approve or deny the request. -* To join the *steering committee*, a *collaborator* will be nominated by a *steering committee* member and the *steering committee* who will approve or deny the request. +* To become a *contributor*, a community member must have a pull request approved and merged into the FAST project main branch. +* To become a *collaborator*, a *contributor* will petition the *steering committee*, who will approve or deny the request. +* To become a *code owner*, a *collaborator* will be (a) nominated by a *steering committee* member or (b) petition the *steering committee*, who will approve or deny the request. +* To join the *steering committee*, a *collaborator* will be nominated by a *steering committee* member and the *steering committee*, who will approve or deny the request. ## Acceptance and consensus seeking process Acceptance of contributions follows the consensus-seeking process. -All pull requests must be approved by a *collaborator* before the pull request can be accepted. +All pull requests must be approved by an assigned *collaborator* before the pull request can be accepted. A *collaborator* will be assigned to a pull request within [a reasonable period of time](#response-time) of the pull request creation. The assignee will be responsible for: + +1. Reviewing the pull request if they are not the creator of it +2. Adding any additional reviewers to review at their discretion +3. Ensuring the pull request is given feedback in [a reasonable period of time](#response-time) from *collaborators* or *code owners* with the expertise to evaluate the changes +4. Merging the pull request + +When a pull request : (a) has a significant impact on the project, (b) is inherently controversial, or (c) has not reached consensus with *collaborators*; add a "status:controversial" label to the pull request for the *steering committee* to review the pull request. Pull requests labeled with "status:controversial" are not approved until the *steering committee* reviews the issue and makes a decision. -Before a pull request is accepted, time should be given to receive input from *collaborators* or *code owners* with the expertise to evaluate the changes. The amount of time can vary but at least 3 days during the typical working week and 5 days over weekends should be given to account for international time differences and work schedules. +Additionally, *owners* can temporarily enable [interaction limits](https://help.github.com/articles/limiting-interactions-with-your-repository/) to allow a "cool-down" period when hot topics become disruptive. -When a pull request : (a) has a significant impact on the project, (b) is inherently controversial, or (c) has not reached consensus with *collaborators*; add a "controversial" label to the pull request for the *steering committee* to review the pull request. Pull requests labeled with "controversial" are not approved until the *steering committee* reviews the issue and makes a decision. +Specific *collaborators* or *code owners* can be added to a pull request by including their user alias in the "Reviewers" section. -Additionally, *owners*, can temporarily enable [interaction limits](https://help.github.com/articles/limiting-interactions-with-your-repository/) to allow a "cool-down" period when hot topics become disruptive. +### Response time -Specific *collaborators* or *code owners* can be added to a pull request by including their user alias. +The amount of time can vary but at least 3 days during the typical working week and 5 days over weekends should be given to account for international time differences and work schedules. This is considered a reasonable period of time. ## Stability policy -An essential consideration in every pull request is its impact on the system. To manage impacts, we work collectively to ensure that we do not introduce unnecessary breaking changes, performance or functional regressions, or negative impacts on usability for users or supported partners. +An essential consideration in every pull request is its impact on the system. To manage impacts, we work collectively to ensure that we do not introduce unnecessary breaking changes, performance or functional regressions, or negative impacts on usability for users or supported partners. To learn more about our approaches to planning and releases, see [our release planning document](../community/release-planning.md). ## Developer's Certificate of Origin 1.1 @@ -166,7 +198,7 @@ By making a contribution to this project, I certify that: * a. The contribution was created in whole or in part by me and I have the right to submit it under the open source license indicated in the file; or * b. The contribution is based upon previous work that, to the best of my knowledge, is covered under an appropriate open source license and I have the right under that license to submit that work with modifications, whether created in whole or in part by me, under the same open source license (unless I am permitted to submit under a different license), as indicated in the file; or -* c. The contribution was provided directly to me by some other person who certified (a), (b) or (c) and I have not modified it. +* c. The contribution was provided directly to me by some other person who certified (a), (b), or (c) and I have not modified it. * d. I understand and agree that this project and the contribution are public and that a record of the contribution (including all personal information I submit with it, including my sign-off) is maintained indefinitely and may be redistributed consistent with this project or the open source license(s) involved. ## Resources @@ -174,6 +206,6 @@ By making a contribution to this project, I certify that: Several open source projects have influenced our contribution policy: * [Project Governance @Node](https://nodejs.org/en/about/governance/) -* [Contributions @Node](https://github.com/nodejs/node/blob/master/CONTRIBUTING.md) +* [Contributions @Node](https://github.com/nodejs/node/blob/main/CONTRIBUTING.md) * [Open Source @GitHub](https://github.com/blog/2039-adopting-the-open-code-of-conduct) * [Open Source examples @todogroup](https://github.com/todogroup/policies) diff --git a/LICENSE b/LICENSE index 21071075c24..630e2d95d5e 100644 --- a/LICENSE +++ b/LICENSE @@ -1,3 +1,5 @@ + FAST - https://www.fast.design/ + MIT License Copyright (c) Microsoft Corporation. All rights reserved. diff --git a/README.md b/README.md index 50ff904ee83..c70267bd719 100644 --- a/README.md +++ b/README.md @@ -1,118 +1,70 @@ - -![fast_banner_github_914.png](https://static.fast.design/assets/fast_banner_github_914.png) - # FAST [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT) -[![lerna](https://img.shields.io/badge/maintained%20with-lerna-cc00ff.svg)](https://lerna.js.org/) -[![TypeScript](https://img.shields.io/badge/%3C%2F%3E-TypeScript-%230074c1.svg)](http://www.typescriptlang.org/) +[![TypeScript](https://img.shields.io/badge/%3C%2F%3E-TypeScript-%230074c1.svg)](https://www.typescriptlang.org/) [![code style: prettier](https://img.shields.io/badge/code_style-prettier-f8bc45.svg)](https://github.com/prettier/prettier) -[![Maintainability](https://api.codeclimate.com/v1/badges/8a74621e634a6e9b9561/maintainability)](https://codeclimate.com/github/Microsoft/fast/maintainability) -[![Test Coverage](https://api.codeclimate.com/v1/badges/8a74621e634a6e9b9561/test_coverage)](https://codeclimate.com/github/Microsoft/fast/test_coverage) -![workflows](https://github.com/microsoft/fast/workflows/CI%20-%20FAST/badge.svg?branch=master&event=push) +[![Validate PRs](https://github.com/microsoft/fast/actions/workflows/ci-validate-pr.yml/badge.svg)](https://github.com/microsoft/fast/actions/workflows/ci-validate-pr.yml) +[![Validate Platforms/Browsers](https://github.com/microsoft/fast/actions/workflows/ci-validate-platforms.yml/badge.svg)](https://github.com/microsoft/fast/actions/workflows/ci-validate-platforms.yml) [![Discord](https://img.shields.io/badge/chat%20on-discord-7289da.svg)](https://discord.gg/FcSNfg4) [![Twitter](https://img.shields.io/twitter/follow/fast_ui.svg?style=social&label=Follow)](https://twitter.com/intent/follow?screen_name=fast_ui) -This is the FAST monorepo, containing web component packages, tools, examples, and documentation. FAST tech can be used Γ  la carte or as a suite to build enterprise-grade websites, applications, components, design systems, and more. - -**TL;DR** - -* Create reusable UI components based on web component standards. -* Use our standard library of pre-built web components in your apps. -* Choose between two *adaptive* design systems: Fluent Design and FAST Frame. -* Build your own design system without re-implementing component logic. -* Integrate with any front-end framework or build system. - :star: We appreciate your star, it helps! ## Introduction -FAST is a collection of JavaScript packages centered around web standards, designed to help you efficiently tackle some of the most common challenges in website and application design and development. - -Have you ever needed a reusable set of UI components that you could drop into your app and have an amazing experience? _**That's FAST.**_ - -Have you ever needed to create your own components, and share them across your company, including across groups that use different, incompatible front-end frameworks? _**That's FAST.**_ +FAST is dedicated to providing support for native Web Components and modern Web Standards, and it's designed to help you efficiently tackle some of the most common challenges in website and application design and development. -Have you ever needed to implement a branded experience or a design language like Microsoft's Fluent UI or Google's Material Design? _**That's FAST.**_ +**TL;DR** -Have you ever wanted to improve your app's startup time, render speed, or memory consumption? _**That's FAST.**_ +* Create reusable UI components with `@microsoft/fast-element`, all based on W3C Web Component standards. +* Integrate FAST Web Components with any library, framework, or build system. You can adopt incrementally without re-writing your existing systems. -Have you ever wanted to adopt more web standards and build your site or app on a native web foundation that's immune to the shifting sands of the modern JavaScript front-end landscape? _**That's FAST.**_ +For an in-depth explanation of FAST [see our docs introduction](https://fast.design/docs/introduction/). -Let's take a look at what each of FAST's core packages gives us today. +## Packages -### fast-element +### `@microsoft/fast-element` [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT) [![npm version](https://badge.fury.io/js/%40microsoft%2Ffast-element.svg)](https://badge.fury.io/js/%40microsoft%2Ffast-element) -The `@microsoft/fast-element` library is a lightweight means to easily building performant, memory-efficient, standards-compliant Web Components. FAST Elements work in every major browser and can be used in combination with any front-end framework or even without a framework. To get up and running with `@microsoft/fast-element` see [the Getting Started guide](http://fast.design/docs/fast-element/getting-started). +The `@microsoft/fast-element` library is a lightweight means to easily build performant, memory-efficient, standards-compliant Web Components. FAST Elements work in every major browser and can be used in combination with any front-end framework or even without a framework. To get up and running with `@microsoft/fast-element` see [the Getting Started guide](https://fast.design/docs/fast-element/getting-started). -### fast-foundation +### `@fluentui/web-components` [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT) -[![npm version](https://badge.fury.io/js/%40microsoft%2Ffast-foundation.svg)](https://badge.fury.io/js/%40microsoft%2Ffast-foundation) - -The `@microsoft/fast-foundation` package is a library of Web Component classes, templates, and other utilities intended to be composed into registered Web Components by design systems (e.g. Fluent Design, Material Design, etc.). The exports of this package can generally be thought of as un-styled base components that implement semantic and accessible markup and behavior. +[![npm version](https://badge.fury.io/js/%40fluentui%2Fweb-components.svg)](https://badge.fury.io/js/%40fluentui%2Fweb-components) -This package does not export Web Components registered as [custom elements](https://developer.mozilla.org/en-US/docs/Web/Web_Components/Using_custom_elements) - it exports parts and pieces intended to be *composed* into Web Components, allowing you to implement your own design language by simply applying CSS styles and behaviors without having to write all the JavaScript that's involved in building production-quality component implementations. +`@fluentui/web-components` is a library of Web Components based on the Fluent design language, built with `@microsoft/fast-element`. -### fast-components - -[![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT) -[![npm version](https://badge.fury.io/js/%40microsoft%2Ffast-components.svg)](https://badge.fury.io/js/%40microsoft%2Ffast-components) - -`@microsoft/fast-components` is a library of Web Components that *composes* the exports of `@microsoft/fast-foundation` with stylesheets aligning to the FAST design language. This composition step registers a custom element. See the [quick start](http://fast.design/components/getting-started) to get started using the components. - -### fast-components-msft -**This package has been moved to [FluentUI](https://github.com/microsoft/fluentui/) and has been renamed to `@fluentui/web-components`** -[![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT) -[![npm version](https://badge.fury.io/js/%40microsoft%2Ffast-components-msft.svg)](https://badge.fury.io/js/%40microsoft%2Ffast-components-msft) +The source for `@fluentui/web-components` is hosted in [the Fluent UI monorepo](https://github.com/microsoft/fluentui/tree/master/packages/web-components). -`@fluentui/web-components` is a library of Web Components that *composes* `@microsoft/fast-foundation`. `@fluentui/web-components` makes use of different stylesheets and may include components that specifically support Microsoft's Fluent design language. +## Getting Started -### Component Explorer +We hope you're excited by the possibilities that FAST presents. But, you may be wondering where to start. Here are a few statements that describe various members of our community. We recommend that you pick the statement you most identify with and follow the links where they lead. You can always come back and explore another topic at any time. -Launch our [Component Explorer](https://explore.fast.design) to experience our [FAST Components](https://www.npmjs.com/package/@microsoft/fast-components) and development tools. +* "I just want ready-made components!" + * [Check out the FluentUI Web Components.](https://docs.microsoft.com/en-us/fluent-ui/web-components/) +* "I want to build my own components." + * [Jump to the fast-element docs.](https://fast.design/docs/getting-started/quick-start) +* "I need to integrate FAST with another framework or build system." + * [Jump to the integration docs.](https://fast.design/docs/integrations) +* "I want to look at a quick reference." + * [Jump to the Cheat Sheet](https://fast.design/docs/1.x/resources/cheat-sheet) -## Getting Started +## Roadmap -If you're looking to get started using our components right away, take a look at [the components quick start](http://fast.design/docs/components/getting-started). You'll also want to check out [our integrations](http://fast.design/docs/integrations/introduction) if you're looking to add the components into a Webpack build or incorporate them with another front-end framework. For those interested in implementing their own design system or customizing the styles of the components, after you [have a look at the components](http://fast.design/docs/components/getting-started), you'll want to read through [our styling docs](http://fast.design/docs/design/introduction). Finally, if your goal is to build your own components or apps with `@microsoft/fast-element`, you can learn all about that in our [guide to building web components with FASTElement](http://fast.design/docs/fast-element/getting-started). +Major features for the FAST project can be found in the [roadmap](https://github.com/orgs/microsoft/projects/240/views/1). ## Joining the Community Looking to get answers to questions or engage with us in realtime? Our community is most active [on Discord](https://discord.gg/FcSNfg4). Submit requests and issues on [GitHub](https://github.com/Microsoft/fast/issues/new/choose), or join us by contributing on [some good first issues via GitHub](https://github.com/Microsoft/fast/labels/community:good-first-issue). -We look forward to building an amazing open source community with you! - -## Features & benefits - -### Unopinionated - -There are a million and one great ways to build your next website or application. To support the technologies you choose, creating unopinionated code is at the center of every decision we make in FAST. - -This principle of being unopinionated manifests in several important ways including: - -* A flat component architecture that lets you compose what you need without struggling with rigid patterns and complex objects. -* Separating base components from styles and design systems to support multiple implementations without re-writing or duplicating styles. Use the design system to customize existing styled components, or build your own styles, with your design system, without having to rebuild or duplicate the base components. -* Framework agnostic tooling that lets you use our development tools with any view framework. -* The ability to replace almost any FAST package with your package of choice. Get started with our animation package and add more as you need them. Alternatively, use our suite of packages to build your next project from the ground up; it's your call. +Get started here with the [Contributor Guide](https://www.fast.design/docs/community/contributor-guide). -### UI development and style guide tools - -When developing components and views, excellent development tooling can make all the difference. FAST offers development and style guide tools that work with FAST components, components from other frameworks, or your components. - -Try out component properties with an auto-generated property UI, get a live preview of the code based on any property’s configuration, preview localization (RTL/LTR) and themes, and preview component compositing with a transparency grid. - -Also, we built FAST development tools from re-usable packages, so if you have special needs, you can build your tools from the same shared libraries. - -### Bring your design system - -Widely available design systems from companies like Microsoft (Fluent), Google (Material), or Salesforce (Lightning) are useful when it is essential to align with a platform or take advantage of a polished system at low cost, but many companies have a design system of their own, and some may have multiple design systems or variations. - -Because FAST has abstracted base components from their style, you get a head start on your design system by building on top of tried and true base components and style libraries like our offerings for color, animation, and elevation. +We look forward to building an amazing open source community with you! ## Contact diff --git a/SECURITY.md b/SECURITY.md index 1805721ca58..06e9544e190 100644 --- a/SECURITY.md +++ b/SECURITY.md @@ -12,7 +12,7 @@ If you believe you have found a security vulnerability in any Microsoft-owned re Instead, please report them to the Microsoft Security Response Center (MSRC) at [https://msrc.microsoft.com/create-report](https://msrc.microsoft.com/create-report). -If you prefer to submit without logging in, send email to [secure@microsoft.com](mailto:secure@microsoft.com). If possible, encrypt your message with our PGP key; please download it from the the [Microsoft Security Response Center PGP Key page](https://www.microsoft.com/en-us/msrc/pgp-key-msrc). +If you prefer to submit without logging in, send an email to [secure@microsoft.com](mailto:secure@microsoft.com). If possible, encrypt your message with our PGP key. Please download it from the [Microsoft Security Response Center PGP Key page](https://www.microsoft.com/en-us/msrc/pgp-key-msrc). You should receive a response within 24 hours. If for some reason you do not, please follow up via email to ensure we received your original message. Additional information can be found at [microsoft.com/msrc](https://www.microsoft.com/msrc). diff --git a/api-extractor.json b/api-extractor.json new file mode 100644 index 00000000000..eb55f1b5f2d --- /dev/null +++ b/api-extractor.json @@ -0,0 +1,16 @@ +{ + "$schema": "https://developer.microsoft.com/json-schemas/api-extractor/v7/api-extractor.schema.json", + "mainEntryPointFilePath": "/dist/dts/index.d.ts", + "apiReport": { + "enabled": true, + "reportFolder": "/docs", + "reportFileName": "api-report" + }, + "docModel": { + "enabled": true, + "apiJsonFilePath": "/dist/.api.json" + }, + "dtsRollup": { + "enabled": true + } +} \ No newline at end of file diff --git a/azure-pipelines-cd.yml b/azure-pipelines-cd.yml new file mode 100644 index 00000000000..ac03787375f --- /dev/null +++ b/azure-pipelines-cd.yml @@ -0,0 +1,62 @@ +trigger: none +pr: none + +# The `resources` specify the location and version of the 1ES PT. +resources: + repositories: + - repository: fastPipelines + type: git + name: fast/FASTPipelineTemplates + ref: main + +pool: + vmImage: "ubuntu-latest" + +variables: + npm_config_cache: $(Pipeline.Workspace)/.npm + +steps: + - checkout: self + persistCredentials: "true" + + - script: | + git config --global user.email fastsvc@microsoft.com + git config --global user.name "Microsoft FAST Builds" + git remote set-url origin https://$(GH_TOKEN)@github.com/microsoft/fast.git + + - task: UseNode@1 + inputs: + version: "22.x" + displayName: "Install Node.js" + + - task: Cache@2 + inputs: + key: 'npm | "$(Agent.OS)" | package-lock.json' + restoreKeys: | + npm | "$(Agent.OS)" + path: $(npm_config_cache) + displayName: "Cache npm" + + - script: | + npm ci + displayName: "Install package dependencies" + + - script: | + npm run build + displayName: "Build workspaces" + + - script: | + npm run publish-ci + displayName: "Use Beachball publish to bump and commit without publishing" + env: + GH_TOKEN: $(GH_TOKEN) + + - script: | + mkdir publish_artifacts + displayName: "Create a folder for published artifacts" + + - script: | + npm pack --workspace "packages" --pack-destination "publish_artifacts" + displayName: "Pack NPM packages to tgz" + + - template: FAST.Release.PipelineTemplate.yml@fastPipelines # Template reference diff --git a/azure-pipelines-ci.yml b/azure-pipelines-ci.yml new file mode 100644 index 00000000000..baec80b4240 --- /dev/null +++ b/azure-pipelines-ci.yml @@ -0,0 +1,66 @@ +pr: + - main + +# The `resources` specify the location and version of the 1ES PT. +resources: + repositories: + - repository: 1esPipelines + type: git + name: 1ESPipelineTemplates/1ESPipelineTemplates + ref: refs/tags/release + +extends: + # The pipeline extends the 1ES PT which will inject different SDL and compliance tasks. + # For non-production pipelines, use "Unofficial" as defined below. + # For productions pipelines, use "Official". + template: v1/1ES.Official.PipelineTemplate.yml@1esPipelines + parameters: + # Update the pool with your team's 1ES hosted pool. + pool: + name: OneESPool # Name of your hosted pool + image: HostedPoolLinuxImage # Name of the image in your pool. If not specified, first image of the pool is used + os: linux # OS of the image. This value cannot be a variable. Allowed values: windows, linux, macOS + sdl: + sourceAnalysisPool: + name: OneESPool # Name of your hosted pool + image: HostedPoolWindowsImage # Name of the image in your pool. If not specified, first image of the pool is used + os: windows # OS of the image. Allowed values: windows, linux, macOS + stages: + - stage: Stage + jobs: + - job: HostJob + # If the pipeline publishes artifacts, use `templateContext` to define the artifacts. + # This will enable 1ES PT to run SDL analysis tools on the artifacts and then upload them. + templateContext: + outputs: + - output: pipelineArtifact + targetPath: $(System.ArtifactsDirectory) + artifactName: drop + + variables: + npm_config_cache: $(Pipeline.Workspace)/.npm + + steps: + - checkout: self + persistCredentials: "true" + + - task: UseNode@1 + inputs: + version: "22.x" + displayName: "Install Node.js" + + - task: Cache@2 + inputs: + key: 'npm | "$(Agent.OS)" | package-lock.json' + restoreKeys: | + npm | "$(Agent.OS)" + path: $(npm_config_cache) + displayName: "Cache npm" + + - script: | + npm ci + displayName: "Install package dependencies" + + - script: | + npm run build + displayName: "Build workspaces" diff --git a/beachball.config.js b/beachball.config.js new file mode 100644 index 00000000000..2cfdab1fde1 --- /dev/null +++ b/beachball.config.js @@ -0,0 +1,14 @@ +module.exports = { + ignorePatterns: [ + ".ignore", + ".github/", + ".prettierrc", + ".vscode/", + "jest..js", + "src/e2e/", + "src/tests/", + "src/fixtures/**", + // This one is especially important (otherwise dependabot would be blocked by change file requirements) + "package-lock.json", + ] +}; diff --git a/build/clean.js b/build/clean.js index eb5308d94b8..e49bf751681 100644 --- a/build/clean.js +++ b/build/clean.js @@ -3,7 +3,7 @@ * Usage: node build/clean.js %path% */ const path = require("path"); -const rimraf = require("rimraf"); +const { rimraf } = require("rimraf"); const argv = require("yargs").argv; /** @@ -15,8 +15,12 @@ const paths = argv._; * Function to remove a given path */ function cleanPath(cleanPath) { - const removePath = path.resolve(process.cwd(), cleanPath) - rimraf(removePath, () => { + if (!cleanPath) { + console.error("No path specified."); + process.exit(1); + } + const removePath = path.resolve(process.cwd(), cleanPath); + rimraf(removePath).then(() => { console.log(removePath, "cleaned"); }); } diff --git a/build/convert-readme.js b/build/convert-readme.js index a62a24c2797..02690ee00c9 100644 --- a/build/convert-readme.js +++ b/build/convert-readme.js @@ -3,8 +3,8 @@ * Usage: node build/convert-readme.js %path% */ const path = require("path"); -const glob = require("glob"); const fs = require("fs"); +const { globSync } = require("glob"); const argv = require("yargs").argv; const MarkdownIt = require("markdown-it"); @@ -45,29 +45,27 @@ const paths = argv._; function exportReadme(readmePath) { const readmePaths = path.resolve(process.cwd(), srcDir); - glob(readmePaths, void 0, function (error, files) { - files.forEach(filePath => { - let documentation = startFile; - const markdown = fs.readFileSync(filePath, "utf8"); - const exportPath = filePath.replace(/README\.md/, readmePath); + globSync(readmePaths, void 0).forEach(filePath => { + let documentation = startFile; + const markdown = fs.readFileSync(filePath, "utf8"); + const exportPath = filePath.replace(/README\.md/, readmePath); - if (markdown.length !== 0) { - documentation += md.render(markdown); - } else { - documentation += emptyFile; - } + if (markdown.length !== 0) { + documentation += md.render(markdown); + } else { + documentation += emptyFile; + } - documentation += endFile; + documentation += endFile; - if (!fs.existsSync(exportPath)) { - fs.mkdirSync(exportPath); - } + if (!fs.existsSync(exportPath)) { + fs.mkdirSync(exportPath); + } - fs.writeFileSync( - path.resolve(exportPath, "documentation.tsx"), - documentation - ); - }); + fs.writeFileSync( + path.resolve(exportPath, "documentation.tsx"), + documentation + ); }); } diff --git a/build/convert-schemas.js b/build/convert-schemas.js index 0b1a4cb6f60..1077d78c3e2 100644 --- a/build/convert-schemas.js +++ b/build/convert-schemas.js @@ -4,7 +4,7 @@ */ const path = require("path"); const fs = require("fs"); -const glob = require("glob"); +const { globSync } = require("glob"); const rootDir = path.resolve(process.cwd()); const srcSchemaPaths = "src/**/*.schema.ts"; @@ -18,7 +18,7 @@ let exit = 0; function copySchemaFiles() { const resolvedSrcSchemaPaths = path.resolve(rootDir, srcSchemaPaths); - glob.sync(resolvedSrcSchemaPaths, void 0).forEach(function(filePath) { + globSync(resolvedSrcSchemaPaths, void 0).forEach(function(filePath) { let destSchemaPath = filePath.replace(/(\bsrc\b)(?!.*\1)/, destDir); destSchemaPath = destSchemaPath.substr(0, destSchemaPath.lastIndexOf(".ts")) + ".json"; diff --git a/build/copy.js b/build/copy.js new file mode 100644 index 00000000000..474dad033bb --- /dev/null +++ b/build/copy.js @@ -0,0 +1,58 @@ +const fs = require("fs"); +const path = require("path"); +const { glob } = require("glob"); + +/** + * Recursively create directories + */ +function ensureDir(dirPath) { + if (!fs.existsSync(dirPath)) { + fs.mkdirSync(dirPath, { recursive: true }); + } +} + +/** + * Copy a single file + */ +function copyFile(src, dest) { + ensureDir(path.dirname(dest)); + fs.copyFileSync(src, dest); +} + +async function copy(files, destination, config = { flat: true, verbose: true, up: true }) { + try { + ensureDir(destination); + + const allFiles = []; + for (const pattern of files) { + const matches = await glob(pattern, { nodir: true }); + allFiles.push(...matches); + } + + for (const file of allFiles) { + let destPath; + if (config.flat) { + destPath = path.join(destination, path.basename(file)); + } else { + destPath = path.join(destination, file); + } + + copyFile(file, destPath); + + if (config.verbose) { + console.log(`Copied ${file} to ${destPath}`); + } + } + } catch (err) { + console.error(err); + process.exit(1); + } +} + +/** + * Copy files from one place to another. + * @param {string[]} files - Paths and globs to copy + * @param {string} destination - Directory to copy the files to + * @param {{ flat?: boolean; verbose?: boolean; up?: boolean; }} config - Configuration options. + */ +module.exports = copy; diff --git a/build/get-package-json.js b/build/get-package-json.js new file mode 100644 index 00000000000..fb5ea230c75 --- /dev/null +++ b/build/get-package-json.js @@ -0,0 +1,25 @@ +const path = require("path"); +const fs = require("fs"); + +/** + * Resolves the directory of the package.json for a given dependency. + * @param {string} name - the package name + * @returns + * + * @description + * NodeJS exports fields prevent arbitrarily resolving files in a package + * that are not explicitly enumerated in the exports field of the package. + * This function provides a mechanism to resolve the package 'root' by package name, + * allowing file-system retrieval by relative path for arbitrary files outside of + * Node's module system. + */ +exports.getPackageJsonDir = (name, options) => { + const entry = require.resolve(name, options).toString(); + let dir = path.parse(entry).dir; + + while (!fs.existsSync(path.resolve(dir, "package.json"))) { + dir = path.parse(dir).dir; + } + + return dir; +}; diff --git a/build/helpers/__tests__/src/bar/bar.ts b/build/helpers/__tests__/src/bar/bar.ts deleted file mode 100644 index 87c1ff593dc..00000000000 --- a/build/helpers/__tests__/src/bar/bar.ts +++ /dev/null @@ -1 +0,0 @@ -export default class Bar {} diff --git a/build/helpers/__tests__/src/bar/index.ts b/build/helpers/__tests__/src/bar/index.ts deleted file mode 100644 index 8fb18cc232f..00000000000 --- a/build/helpers/__tests__/src/bar/index.ts +++ /dev/null @@ -1,2 +0,0 @@ -import Bar from "./bar"; -export { Bar }; diff --git a/build/helpers/__tests__/src/foo/foo.ts b/build/helpers/__tests__/src/foo/foo.ts deleted file mode 100644 index 7804111002d..00000000000 --- a/build/helpers/__tests__/src/foo/foo.ts +++ /dev/null @@ -1 +0,0 @@ -export default class Foo {} diff --git a/build/helpers/__tests__/src/foo/index.ts b/build/helpers/__tests__/src/foo/index.ts deleted file mode 100644 index 993fb691db1..00000000000 --- a/build/helpers/__tests__/src/foo/index.ts +++ /dev/null @@ -1,2 +0,0 @@ -import Foo from "./foo"; -export default Foo; diff --git a/build/helpers/__tests__/src/index.ts b/build/helpers/__tests__/src/index.ts deleted file mode 100644 index 38d914e0a84..00000000000 --- a/build/helpers/__tests__/src/index.ts +++ /dev/null @@ -1,11 +0,0 @@ -/** - * Example formatting from fast-components-react-base - */ -import Foo from "./foo"; -export { Foo }; -export * from "./foo"; - -/** - * Example formatting from fast-component-react-msft - */ -export * from "./bar"; diff --git a/build/helpers/__tests__/src/missingExport.ts b/build/helpers/__tests__/src/missingExport.ts deleted file mode 100644 index 7ec37687402..00000000000 --- a/build/helpers/__tests__/src/missingExport.ts +++ /dev/null @@ -1,4 +0,0 @@ -/** - * Example with missing exports - */ -export * from "./bar"; \ No newline at end of file diff --git a/build/helpers/file-includes-all-subdirectories-as-named-exports.spec.ts b/build/helpers/file-includes-all-subdirectories-as-named-exports.spec.ts deleted file mode 100644 index 6e3867061f4..00000000000 --- a/build/helpers/file-includes-all-subdirectories-as-named-exports.spec.ts +++ /dev/null @@ -1,16 +0,0 @@ -import path from "path"; -import { includesAllSubdirectoriesAsNamedExports } from "./file-includes-all-subdirectories-as-named-exports"; - -describe("file-includes-all-subdirectories-as-named-exports.ts", (): void => { - test("should export all components in the __tests__ directory index.ts", () => { - expect(() => { - includesAllSubdirectoriesAsNamedExports(path.resolve(__dirname, "__tests__/src/index.ts")); - }).not.toThrow(); - }); - - test("should throw an error if exports are missing in the __tests__ directory missingExport.ts", () => { - expect(() => { - includesAllSubdirectoriesAsNamedExports(path.resolve(__dirname, "__tests__/src/missingExport.ts")) - }).toThrow(); - }); -}); diff --git a/build/helpers/file-includes-all-subdirectories-as-named-exports.ts b/build/helpers/file-includes-all-subdirectories-as-named-exports.ts deleted file mode 100644 index 9165ae3d5c7..00000000000 --- a/build/helpers/file-includes-all-subdirectories-as-named-exports.ts +++ /dev/null @@ -1,25 +0,0 @@ -import path from "path"; -import fs from "fs"; -import { pascalCase } from "../../packages/utilities/fast-web-utilities"; - -/** - * Verifies all components in source directory are exported, directories listed in "excludes" parameter are ignored - */ -export function includesAllSubdirectoriesAsNamedExports(indexFile: string, excludes?: string[]): boolean { - // Get the folders in the indexFile directory to compare to export listing - const directoryPath: string = path.dirname(indexFile); - const components: string[] = fs.readdirSync(directoryPath) - .map((name: string) => path.join(directoryPath, name)) - .filter((source: string) => fs.statSync(source).isDirectory()) - .map((entry: string) => pascalCase(path.basename(entry))); - - // Get listing of all exports and compare against folder listings - const foundExports: any = Object.keys(require(path.resolve(__dirname, indexFile))); - const missingExports: string[] = components.filter((component: string) => !foundExports.includes(component) && excludes.indexOf(component) !== -1); - - if (missingExports.length === 0) { - return true; - } else { - throw new Error(`Missing exports: ${missingExports}`); - } -} \ No newline at end of file diff --git a/build/package.json b/build/package.json new file mode 100644 index 00000000000..51036fa5cf4 --- /dev/null +++ b/build/package.json @@ -0,0 +1,6 @@ +{ + "name": "@microsoft/fast-build", + "description": "Build utilities for FAST monorepo", + "version": "0.0.0", + "private": true +} diff --git a/build/releasing/customRenderers.ts b/build/releasing/customRenderers.ts new file mode 100644 index 00000000000..3da598215d1 --- /dev/null +++ b/build/releasing/customRenderers.ts @@ -0,0 +1,87 @@ +import { spawnSync } from "child_process"; +import { Octokit } from "@octokit/rest"; +import { PackageChangelogRenderInfo, ChangelogEntry } from "beachball"; +import { getPullRequestForCommit, repoDetails } from "./github"; + +const githubPAT = process.env.GITHUB_TOKEN; +if (!githubPAT && (process.argv.includes("bump") || process.argv.includes("publish"))) { + console.warn( + "\nGITHUB_TOKEN environment variable not found. GitHub requests may be rate-limited.\n" + ); +} + +// Octokit is used to access the GitHub REST API +const github = new Octokit({ + ...repoDetails, + ...(githubPAT && { auth: "token " + githubPAT }), +}); + +const repoUrl = `https://github.com/${repoDetails.owner}/${repoDetails.repo}`; + +export async function renderHeader( + renderInfo: PackageChangelogRenderInfo +): Promise { + const { + newVersionChangelog: { tag, version, date }, + previousJson, + } = renderInfo; + + // Link to the tag on github + const header = tag ? `[${version}](${repoUrl}/tree/${tag})` : version; + + // Also include a compare link to the previous tag if available + const previousTag = previousJson?.entries?.[0]?.tag; + const compareLink = + tag && previousTag + ? ` \n[Compare changes](${repoUrl}/compare/${previousTag}..${tag})` + : ""; + + return `## ${header}\n\n${date.toUTCString()}${compareLink}`; +} + +export async function renderEntry(entry: ChangelogEntry): Promise { + // Link to the PR for this changelog entry (or the commit if PR isn't found) + const prNumber = await _getPrNumber(entry); + const commitLink = prNumber + ? `[PR #${prNumber}](${repoUrl}/pull/${prNumber})` + : `[commit](${repoUrl}/commit/${entry.commit})`; + return `- ${entry.comment} (${commitLink} by ${entry.author})`; +} + +async function _getPrNumber(entry: ChangelogEntry): Promise { + // Look for (presumably) the PR number at the end of the first line of the commit + try { + // Get the actual commit message which should contain the PR number + const logResult = spawnSync("git", [ + "log", + "--pretty=format:%s", + "-n", + "1", + entry.commit, + ]); + if (logResult.status === 0) { + const message = logResult.stdout.toString().trim(); + const prMatch = message.split(/\r?\n/)[0].match(/\(#(\d+)\)$/m); + if (prMatch) { + return Number(prMatch[1]); + } + } + } catch (ex) { + console.log( + `Could not get commit message for ${entry.commit} to find PR number (trying another method):`, + ex + ); + } + + // Or fetch from GitHub API + console.log(`Attempting to fetch pull request corresponding to ${entry.commit}...`); + const pr = await getPullRequestForCommit({ + commit: entry.commit, + github, + repoDetails: repoDetails, + }); + if (pr) { + console.log("...success!"); // failure message is logged by getPullRequestForCommit + return pr.number; + } +} diff --git a/build/releasing/github/constants.ts b/build/releasing/github/constants.ts new file mode 100644 index 00000000000..03007df171d --- /dev/null +++ b/build/releasing/github/constants.ts @@ -0,0 +1,6 @@ +import { IRepoDetails } from "./types"; + +export const repoDetails: IRepoDetails = { + owner: "microsoft", + repo: "fast", +}; diff --git a/build/releasing/github/index.ts b/build/releasing/github/index.ts new file mode 100644 index 00000000000..d21951f0551 --- /dev/null +++ b/build/releasing/github/index.ts @@ -0,0 +1,3 @@ +export * from "./constants"; +export * from "./pull-requests"; +export * from "./types"; diff --git a/build/releasing/github/pull-requests.ts b/build/releasing/github/pull-requests.ts new file mode 100644 index 00000000000..00adaef5566 --- /dev/null +++ b/build/releasing/github/pull-requests.ts @@ -0,0 +1,73 @@ +import { Octokit } from "@octokit/rest"; +import { IPullRequest, IRepoDetails } from "./types"; + +export interface IGetPullRequestFromCommitParams { + github: Octokit; + repoDetails: IRepoDetails; + // Commit hash + commit: string; + // Provide this to have it included in the resulting IPullRequest + authorEmail?: string; + verbose?: boolean; +} + +/** + * Get the pull request info corresponding to the given commit. + * (The `author.email` property is only present if `authorEmail` is provided.) + */ +export async function getPullRequestForCommit( + params: IGetPullRequestFromCommitParams +): Promise { + const { github, repoDetails, commit, authorEmail, verbose } = params; + + verbose && console.log(`Looking for the PR containing ${commit}...`); + + try { + // Attempt to directly find the PR corresponding to the commit from the change file + const result = await github.repos.listPullRequestsAssociatedWithCommit({ + commit_sha: commit, + ...repoDetails, + }); + + // Filter out unmerged PRs, in case the commit has been in multiple PRs but only one got merged + // (check merged_at because that's only set if the PR has been merged, whereas merge_commit_sha + // is set even for un-merged PRs, to the most recent intermediate merge) + const prs = result.data.filter(result => !!result.merged_at); + if (prs.length > 1) { + // In case the commit was in PRs to multiple branches or something? + console.warn(`Multiple PRs found for ${commit}:`); + console.warn(prs.map(pr => ` ${pr.url}`).join("\n")); + } + + if (prs[0]) { + verbose && console.log(`Found matching PR #${prs[0].number}.\n`); + return processPullRequestApiResponse(prs[0], authorEmail); + } + } catch (ex) { + console.warn(`Error finding PR for ${commit}`, ex); + return; + } + + console.warn(`Could not find a PR matching ${commit}.`); +} + +/** + * Convert a GitHub API response to an IPullRequest. + * The `author.email` property is only present if `authorEmail` is provided. + */ +export function processPullRequestApiResponse( + pr: + | Octokit.ReposListPullRequestsAssociatedWithCommitResponseItem + | Octokit.SearchIssuesAndPullRequestsResponseItemsItem, + authorEmail?: string +): IPullRequest { + return { + number: pr.number, + url: pr.html_url, + author: { + email: authorEmail, + username: pr.user.login, + url: pr.user.html_url, + }, + }; +} diff --git a/build/releasing/github/types.ts b/build/releasing/github/types.ts new file mode 100644 index 00000000000..41a72d488ed --- /dev/null +++ b/build/releasing/github/types.ts @@ -0,0 +1,18 @@ +export interface IRepoDetails { + owner: string; + repo: string; +} + +/** Simplified info about a pull request. */ +export interface IPullRequest { + number: number; + url: string; + author: IUser; +} + +/** Info about a GitHub user. */ +export interface IUser { + username: string; + url: string; + email?: string; +} diff --git a/build/releasing/index.ts b/build/releasing/index.ts new file mode 100644 index 00000000000..1cf3f245427 --- /dev/null +++ b/build/releasing/index.ts @@ -0,0 +1,19 @@ +import { BeachballConfig } from "beachball"; +import { renderEntry, renderHeader } from "./customRenderers"; + +export const config: BeachballConfig = { + disallowedChangeTypes: ["major"], + groups: [ + { + name: "Microsoft FAST", + include: ["packages/*"], + disallowedChangeTypes: ["major"], + }, + ], + changelog: { + customRenderers: { + renderHeader, + renderEntry, + }, + }, +}; diff --git a/build/releasing/ts-node-register.js b/build/releasing/ts-node-register.js new file mode 100644 index 00000000000..672603b5a5b --- /dev/null +++ b/build/releasing/ts-node-register.js @@ -0,0 +1,14 @@ +const tsNode = require("ts-node"); + +tsNode.register({ + transpileOnly: true, + compilerOptions: { + declaration: true, + esModuleInterop: true, + experimentalDecorators: true, + module: "commonJS", + moduleResolution: "node", + target: "ES6", + }, + skipProject: true, +}); diff --git a/build/testing/applitools/run-msft-docs.js b/build/testing/applitools/run-msft-docs.js deleted file mode 100644 index 624960c6343..00000000000 --- a/build/testing/applitools/run-msft-docs.js +++ /dev/null @@ -1,148 +0,0 @@ -"use strict"; - -let spawn = require("child_process").spawnSync; - -/** - * Get Branch Name using child_process and Git which runs Asynchronously - */ -class Config { - constructor() { - this.domainName = "https://explore.fast.design"; - this.appName = "FASTDNA"; - this.siteName = "Component explorer"; - } - - /** - * Retrieves the Git Branch for the local user account - */ - branchName() { - return spawn("git", ["rev-parse", "--abbrev-ref", "HEAD"]) - .output[1].toString() - .trim(); - } -} -exports.Config = Config; - -/** - * Testing script that can be used across services - */ -class Run { - constructor(eyes, driver, website) { - console.log("Starting tests on: %s", website); - - driver.get(website); - - // Note: There are many ways to navigate/find/select elements on a page. - // Not all are cross-browser compliant and for example, we can't - // use xpath in all browser drivers. As a result, we're using - // navigation though not necessarily most performant but effective. - - // Iterate each components documentation - - driver.navigate().to(`${website}/components/button/`); - eyes.checkWindow("button"); - - driver.navigate().to(`${website}/components/caption/`); - eyes.checkWindow("caption"); - - driver.navigate().to(`${website}/components/checkbox/`); - eyes.checkWindow("checkbox"); - - driver.navigate().to(`${website}/components/dialog/`); - eyes.checkWindow("dialog"); - - driver.navigate().to(`${website}/components/divider/`); - eyes.checkWindow("divider"); - - driver.navigate().to(`${website}/components/flipper/`); - eyes.checkWindow("flipper"); - - driver.navigate().to(`${website}/components/heading/`); - eyes.checkWindow("heading"); - - driver.navigate().to(`${website}/components/hypertext/`); - eyes.checkWindow("hypertext"); - - driver.navigate().to(`${website}/components/image/`); - eyes.checkWindow("image"); - - driver.navigate().to(`${website}/components/label/`); - eyes.checkWindow("label"); - - driver.navigate().to(`${website}/components/metatext/`); - eyes.checkWindow("metatext"); - - driver.navigate().to(`${website}/components/paragraph/`); - eyes.checkWindow("paragraph"); - - driver.navigate().to(`${website}/components/subheading/`); - eyes.checkWindow("subheading"); - - driver.navigate().to(`${website}/components/text-field/`); - eyes.checkWindow("text-field"); - - driver.navigate().to(`${website}/components/toggle/`); - eyes.checkWindow("toggle"); - - driver.navigate().to(`${website}/components/typography/`); - eyes.checkWindow("typography"); - - // Turn on Developer tools and iterate each component - // Xpath selectors do not work in Internet Explorer - // driver.findElement(By.xpath("//button[text()='dev tools']")).click(); - // one possible solution would be to inject data attributes for each component we can bind to. - // For example, data-test="friendly name" - // driver.findElement(By.cssSelector('[data-element="city"]')) - - // Navigate to example views for each component - driver.navigate().to(`${website}/components/button/examples`); - eyes.checkWindow("button example"); - - driver.navigate().to(`${website}/components/caption/examples`); - eyes.checkWindow("caption example"); - - driver.navigate().to(`${website}/components/checkbox/examples`); - eyes.checkWindow("checkbox example"); - - driver.navigate().to(`${website}/components/dialog/examples`); - eyes.checkWindow("dialog example"); - - driver.navigate().to(`${website}/components/divider/examples`); - eyes.checkWindow("divider example"); - - driver.navigate().to(`${website}/components/flipper/examples`); - eyes.checkWindow("flipper example"); - - driver.navigate().to(`${website}/components/heading/examples`); - eyes.checkWindow("heading example"); - - driver.navigate().to(`${website}/components/hypertext/examples`); - eyes.checkWindow("hypertext example"); - - driver.navigate().to(`${website}/components/image/examples`); - eyes.checkWindow("image example"); - - driver.navigate().to(`${website}/components/label/examples`); - eyes.checkWindow("label example"); - - driver.navigate().to(`${website}/components/metatext/examples`); - eyes.checkWindow("metatext example"); - - driver.navigate().to(`${website}/components/paragraph/examples`); - eyes.checkWindow("paragraph example"); - - driver.navigate().to(`${website}/components/subheading/examples`); - eyes.checkWindow("subheading example"); - - driver.navigate().to(`${website}/components/text-field/examples`); - eyes.checkWindow("text-field example"); - - driver.navigate().to(`${website}/components/toggle/examples`); - eyes.checkWindow("toggle example"); - - driver.navigate().to(`${website}/components/typography/examples`); - eyes.checkWindow("typography example"); - } -} - -exports.Run = Run; diff --git a/build/testing/applitools/test-javascript.js b/build/testing/applitools/test-javascript.js deleted file mode 100644 index 0be0ef6f948..00000000000 --- a/build/testing/applitools/test-javascript.js +++ /dev/null @@ -1,144 +0,0 @@ -/** - * @name - * Test Visual User Interfaces - * - * @description - * Used to generate baselines and test the difference of those baselines against future changes. - * - * @example - * To execute on CLI, run `node build/testing/applitools/test-javascript.js` from root directory. - * - * @requires - * You must create environment variables if executing this script locally using CLI. - * - * This can be done one of two recommended ways. - * 1. Update your `~/.bashrc` file. - * export APPLITOOLS_API_KEY=[some value] - * - * 2. Create a `.env` file at the root of your project - * APPLITOOLS_API_KEY=[some value] - * - * - Cirlce CI has these values included as environment variables. - * - The api key can be found in the portal on Applitools. - * - * Selenium WebDriver Dependencies: - * 1. chromedriver.exe is required to be downloaded (https://chromedriver.storage.googleapis.com/index.html) and placed in `./applitools/` folder - * 2. geckodriver.exe is required to be downloaded (https://github.com/mozilla/geckodriver/releases/tag/v0.22.0) and placed in `./applitools/` folder - * For additional drivers visit: https://www.seleniumhq.org/download/ - * - */ - -"use strict"; - -const { Builder, Capabilities } = require("selenium-webdriver"); -const chalk = require("chalk"); -const Eyes = require("eyes.selenium").Eyes; -const { Config, Run } = require("./run-msft-docs.js"); - -/** - * Setup and SDK and batch - * @param {*} eyes - * @param {*} branch - */ -function setup() { - // Initialize SDK using API Key from environment variables - const domain = "https://eyesapi.applitools.com"; - const config = new Config(); - const eyes = new Eyes(domain); - - // Set Applitools Dashboard variables - eyes.setApiKey(process.env.APPLITOOLS_API_KEY); - eyes.setBatch(config.branchName(), process.env.APPLITOOLS_BATCH_ID, 0); - eyes.setIgnoreCaret(true); - - return eyes; -} - -/** - * Startup function used to connect to Applitools and execute tests - */ -function main() { - // Setup Applitools - let eyes = setup(); - - // Set viewports - const viewportLandscape = { width: 1920, height: 1200 }; - const viewportPortrait = { width: 600, height: 800 }; - - // Execute Chrome driver tests - browserDriver(eyes, Capabilities.chrome(), viewportLandscape, viewportPortrait); - - // Execute FireFox driver tests - browserDriver(eyes, Capabilities.firefox(), viewportLandscape, viewportPortrait); -} - -/** - * Setup FireFox WebDriver and run tests - * @param {*} eyes - * @param {*} webDriver - * @param {*} viewportLandscape - * @param {*} viewportPortrait - */ -function browserDriver(eyes, webDriver, viewportLandscape, viewportPortrait) { - const innerDriver = new Builder() - .withCapabilities(webDriver) - .build(); - - innerDriver.getSession().then(function(session) { - runTest(eyes, innerDriver, viewportLandscape); - runTest(eyes, innerDriver, viewportPortrait); - - if (innerDriver) { - innerDriver.quit(); - } - }); -} - -/** - * Execute tests against different drivers (browsers) and viewports - * @param {*} eyes - * @param {*} innerDriver - * @param {*} viewportSize - */ -function runTest(eyes, innerDriver, viewportSize) { - // Config for AppName, SiteName must be set before opening eyes - const config = new Config(); - - eyes.open(innerDriver, config.appName, config.siteName, viewportSize) - .then(function (driver) { - try { - new Run(eyes, driver, config.domainName); - - eyes.close(false).then(function (result) { - handleResult(result); - }); - - } finally { - eyes.abortIfNotClosed(); - } - }); -} - -/** - * Handle the result by logging status to output - * @param {*} result - */ -function handleResult(result) { - const url = result.appUrls.session; - const totalSteps = result.steps; - - if (result.isNew) { - console.log(chalk.yellow("\nNew Baseline Created: %d steps \nView Results at %s"), totalSteps, url); - } else if (result.isPassed) { - console.log(chalk.green("\nAll Steps Passed: %d steps \nView Results at %s"), totalSteps, url); - } else { - console.log(chalk.red("\nTest Failed:\n\t Matches=%d \n\t Missing=%s \n\t MisMatches=%s \nView Results at %s\n"), - result.matches, - result.missing, - result.mismatches, - url - ); - } -} - -main(); \ No newline at end of file diff --git a/build/testing/config-browsers.alpha.js b/build/testing/config-browsers.alpha.js deleted file mode 100644 index 6d6e7701dc5..00000000000 --- a/build/testing/config-browsers.alpha.js +++ /dev/null @@ -1,54 +0,0 @@ -"use strict"; - -const AlphaConfigure = [ - { - 'platform': 'Windows 10', - 'browserName': 'MicrosoftEdge', - 'version': '17.17134', - 'screenResolution': '1280x1024' - }, - { - 'platform': 'Windows 10', - 'browserName': 'internet explorer', - 'version': '11.103', - 'screenResolution': '1400x1050' - }, - { - 'platform': 'Windows 10', - 'browserName': 'chrome', - 'version': '68.0', - 'screenResolution': '1920x1200' - }, - { - 'platform': 'Windows 10', - 'browserName': 'firefox', - 'version': '61.0', - 'screenResolution': '2560x1600' - }, - { - 'platform': 'macOS 10.13', - 'browserName': 'safari', - 'version': '11.1', - 'screenResolution': '2048x1536' - }, - { - 'platformName': 'iOS', - 'platformVersion': '11.3', - 'deviceOrientation': 'PORTRAIT', - 'deviceName': 'iPhone X Simulator', - 'appiumVersion': '1.8.1', - 'browserName': 'Safari' - }, - { - 'platformName': 'Android', - 'platformVersion': '6.0', - 'deviceOrientation': 'PORTRAIT', - 'deviceName': 'Android Emulator', - 'appiumVersion': '1.8.1', - 'browserName': 'Chrome', - 'language': 'en', - 'locale': 'en_US' - } -]; - -exports.AlphaConfigure = AlphaConfigure; \ No newline at end of file diff --git a/build/testing/config-browsers.beta.js b/build/testing/config-browsers.beta.js deleted file mode 100644 index b8580c0f4d8..00000000000 --- a/build/testing/config-browsers.beta.js +++ /dev/null @@ -1,17 +0,0 @@ -"use strict"; - -const { AlphaConfigure } = require("./config-browsers.alpha.js"); - -const BetaConfigure = [ - ...AlphaConfigure, - { - 'platformName': 'iOS', - 'platformVersion': '9.3', - 'deviceOrientation': 'PORTRAIT', - 'deviceName': 'iPad Pro Simulator', - 'appiumVersion': '1.7.1', - 'browserName': 'Safari' - } -]; - -exports.BetaConfigure = BetaConfigure; \ No newline at end of file diff --git a/build/testing/config-browsers.js b/build/testing/config-browsers.js deleted file mode 100644 index 0ac9f85be36..00000000000 --- a/build/testing/config-browsers.js +++ /dev/null @@ -1,56 +0,0 @@ -"use strict"; - -const { AlphaConfigure } = require("./config-browsers.alpha.js"); -const { BetaConfigure } = require("./config-browsers.beta.js"); -const { ReleaseConfigure } = require("./config-browsers.release.js"); - -/** - * Cross Browser Configuration - * - * Different subsets of cross browser / device configurations are used to test - * projects or packages with user interafaces or experiences. - * - * As projects move through the different 'Phases' of development testing - * scenarios increase to become more comprehensive across browsers. - * - * The configurations require updating over time as new browser versions are - * released or as known unstable combinations become apparent. - * - */ - -/** - * Phases of software development - * @type Enum - */ -const Phase = Object.freeze({ - alpha: "alpha", - beta: "beta", - release: "release", -}); - -exports.Phase = Phase; - -/** - * Platform configurations sourced from Selenium and Appium online Configurators. - * - * @see - * https://wiki.saucelabs.com/display/DOCS/Platform+Configurator#/ - * https://www.browserstack.com/automate/node - */ -var Configure = (function () { - function _configure(phase) { - switch (phase) { - case Phase.alpha: - return AlphaConfigure; - case Phase.beta: - return BetaConfigure; - case Phase.release: - default: - return ReleaseConfigure; - } - } - - return _configure; -})(); - -exports.Configure = Configure; diff --git a/build/testing/config-browsers.release.js b/build/testing/config-browsers.release.js deleted file mode 100644 index bee2e999eab..00000000000 --- a/build/testing/config-browsers.release.js +++ /dev/null @@ -1,121 +0,0 @@ -"use strict"; - -const { BetaConfigure } = require("./config-browsers.beta.js"); - -const ReleaseConfigure = [ - ...BetaConfigure, - { - 'platform': 'Windows 8.1', - 'browserName': 'internet explorer', - 'version': '11.0', - 'screenResolution': '1024x768' - }, - { - 'platform': 'Windows 10', - 'browserName': 'chrome', - 'version': '67.0', - 'screenResolution': '1920x1200' - }, - { - 'platform': 'macOS 10.12', - 'browserName': 'safari', - 'version': '11.0', - 'screenResolution': '2048x1536' - }, - { - 'platform': 'macOS 10.12', - 'browserName': 'safari', - 'version': '10.1', - 'screenResolution': '2360x1770' - }, - { - 'platform': 'macOS 10.13', - 'browserName': 'firefox', - 'version': '62.0', - 'screenResolution': '2360x1770' - }, - { - 'platform': 'OS X 10.11', - 'browserName': 'chrome', - 'version': '69.0', - 'screenResolution': '2048x1536' - }, - { - 'platformName': 'iOS', - 'platformVersion': '11.2', - 'deviceOrientation': 'PORTRAIT', - 'deviceName': 'iPhone 8 Plus Simulator', - 'appiumVersion': '1.8.1', - 'browserName': 'Safari' - }, - { - 'platformName': 'iOS', - 'platformVersion': '11.1', - 'deviceOrientation': 'PORTRAIT', - 'deviceName': 'iPhone 7 Simulator', - 'appiumVersion': '1.8.1', - 'browserName': 'Safari' - }, - { - 'platformName': 'iOS', - 'platformVersion': '10.0', - 'deviceOrientation': 'PORTRAIT', - 'deviceName': 'iPad Retina Simulator', - 'appiumVersion': '1.8.0', - 'browserName': 'Safari' - }, - { - 'platformName': 'iOS', - 'platformVersion': '11.0', - 'deviceOrientation': 'PORTRAIT', - 'deviceName': 'iPhone 6s Simulator', - 'appiumVersion': '1.8.1', - 'browserName': 'Safari' - }, - { - 'platformName': 'Android', - 'platformVersion': '7.1', - 'deviceOrientation': 'PORTRAIT', - 'deviceName': 'Samsung Galaxy S7 Edge FHD GoogleAPI Emulator', - 'appiumVersion': '1.8.1', - 'browserName': 'Chrome', - 'language': 'en', - 'locale': 'en_US' - }, - { - 'platformName': 'Android', - 'platformVersion': '7.0', - 'deviceOrientation': 'PORTRAIT', - 'deviceName': 'Samsung Galaxy Tab A 10 GoogleAPI Emulator', - 'appiumVersion': '1.8.1', - 'browserName': 'Chrome', - 'language': 'en', - 'locale': 'en_US' - }, - { - 'platformName': 'Android', - 'platformVersion': '5.1', - 'deviceOrientation': 'PORTRAIT', - 'deviceName': 'Android GoogleAPI Emulator', - 'appiumVersion': '1.8.1', - 'browserName': 'Browser' - }, - { - 'platformName': 'Android', - 'platformVersion': '5.0', - 'deviceOrientation': 'PORTRAIT', - 'deviceName': 'Android Emulator', - 'appiumVersion': '1.8.1', - 'browserName': 'Browser' - }, - { - 'platformName': 'Android', - 'platformVersion': '4.4', - 'deviceOrientation': 'PORTRAIT', - 'deviceName': 'LG Nexus 4 Emulator', - 'appiumVersion': '1.8.1', - 'browserName': 'Browser' - } -]; - -exports.ReleaseConfigure = ReleaseConfigure; \ No newline at end of file diff --git a/build/testing/sauce-labs/test-browsers.js b/build/testing/sauce-labs/test-browsers.js deleted file mode 100644 index 7bfef28b5f5..00000000000 --- a/build/testing/sauce-labs/test-browsers.js +++ /dev/null @@ -1,194 +0,0 @@ -/** - * @name - * Test Browsers, these scripts can launch tests from CLI, although loggin into - * Sauce Labs with the existing organization credentials and key, provides a manual - * testing environment with many different options available. - * - * @description - * Cross browser testing with Selenium Webdriver (browser configurations) and Appium - * (device configurations) for testing on Sauce Labs. The configurations are sourced - * from 'build/testing/config-browsers.js'. - * - * Sauce Labs lets collaborators and contributors execute automated tests against - * Selenium WebDriver on pre-configured browser matrix's. The cross-browser testing - * strategy focuses on the differences between browser rendering engines. There are - * three different configuration files based on feature maturity of ongoing work. Each - * is represented by alpha, beta, and release configuration that defines the platform, - * browser, version, and screen size. Moving from alpha to release increases the test - * scenarios for more comprehensive analysis understanding that production will have - * the highest quality standards. These files are located in `./build/testing`. - * - * @example - * To execute on CLI, - * Alpha: `node build/testing/sauce-labs/test-browsers.js alpha` - * Beta: `node build/testing/sauce-labs/test-browsers.js beta` - * Release: `node build/testing/sauce-labs/test-browsers.js release` - * - * @requires - * You must create environment variables if executing this script locally using CLI. This can be done - * by adding to your '~/.bashrc' file. - * - * export SAUCE_LABS_USER=[some value] - * export SAUCE_LABS_USER=[some value] - * * - * @see - * To understand in detail: - * Getting Started: https://help.crossbrowsertesting.com/selenium-testing/getting-started/javascript/ - * Scripting docs: https://www.seleniumhq.org/docs/03_webdriver.jsp#chapter03-reference - */ - -const { Builder } = require("selenium-webdriver"); -const chalk = require("chalk"); -const { Configure, Phase } = require("../config-browsers.js"); -const { spawn } = require("child_process"); - -// Retrive user/key from environment variables -const username = process.env.SAUCE_LABS_USER; -const accessKey = process.env.SAUCE_LABS_KEY; -const domain = "https://explore.fast.design"; - -// Configure to connect to remote hub -const remoteHub = `http://${username}:${accessKey}@ondemand.saucelabs.com:80/wd/hub`; - -/** - * Get configuration based on the accepted Phase argument - * @param {Phase} phase - * @returns {Configuration based on phase} - */ -const getConfiguration = phase => { - switch (phase) { - case Phase.alpha: - return new Configure(Phase.alpha); - case Phase.beta: - return new Configure(Phase.beta); - case Phase.release: - return new Configure(Phase.release); - default: - console.log( - chalk.red("Invalid Argument : must be 'alpha', 'beta', or 'release'") - ); - return process.exit(1); - } -}; - -// Assign browser configurations to an array -let browsers = getConfiguration(process.argv[2]); - -/** - * Run tests on Sauce Labs - * @param {string} branchName - */ -function test(branchName) { - console.log("Testing Git branch:", branchName); - - // Execute Selenium/Appium Web Drivers on Sauce Labs for each browser configuration - var flows = browsers.map(function (browser) { - // Setup capabilities - let capabilities = { - name: "FAST Documentation", - build: branchName, - tags: "msft-docs", - appiumVersion: browser.appiumVersion, - platform: browser.platform, - platformName: browser.platformName, - platformVersion: browser.platformVersion, - deviceName: browser.deviceName, - orientation: browser.deviceOrientation, - browserName: browser.browserName, - version: browser.version, - screen_resolution: browser.screenResolution, - language: browser.language, - locale: browser.locale, - username: username, - password: accessKey, - extendedDebugging: true, - }; - - // Setup WebDriver - let driver = new Builder() - .withCapabilities(capabilities) - .usingServer(remoteHub) - .build(); - - // Start session and execute test cases - driver.getSession().then(async function () { - try { - await driver.get(domain); - - /** - * Note: There are many ways to nagivate/find elements on a page - * unfortunately, not all are cross-browser compliant. - * As a result, we're using webdriver's navigate. - * - * Add in data-test attributes to each component, page, layout, - * or container we want to capture and select on that. - * - * TODO: After browsers matrix is determined we can fine tune and - * optimize to use other selectors to see what works. If we're - * testing on modern browsers this isn't as much a limitation. - */ - - // Iterate each components documentation - await driver.navigate().to(`${domain}/components/button/`); - await driver.navigate().to(`${domain}/components/caption/`); - await driver.navigate().to(`${domain}/components/checkbox/`); - await driver.navigate().to(`${domain}/components/dialog/`); - await driver.navigate().to(`${domain}/components/divider/`); - await driver.navigate().to(`${domain}/components/flipper/`); - await driver.navigate().to(`${domain}/components/heading/`); - await driver.navigate().to(`${domain}/components/hypertext/`); - await driver.navigate().to(`${domain}/components/image/`); - await driver.navigate().to(`${domain}/components/label/`); - await driver.navigate().to(`${domain}/components/metatext/`); - await driver.navigate().to(`${domain}/components/paragraph/`); - await driver.navigate().to(`${domain}/components/subheading/`); - await driver.navigate().to(`${domain}/components/text-field/`); - await driver.navigate().to(`${domain}/components/toggle/`); - await driver.navigate().to(`${domain}/components/typography/`); - - /** - * Turn on Developer tools and iterate each component - * For example: - * data-test="friendly name" - * driver.findElement(By.cssSelector('[data-element="city"]')) - */ - - // Navigate to example views for each component - await driver.navigate().to(`${domain}/components/button/examples`); - await driver.navigate().to(`${domain}/components/caption/examples`); - await driver.navigate().to(`${domain}/components/checkbox/examples`); - await driver.navigate().to(`${domain}/components/dialog/examples`); - await driver.navigate().to(`${domain}/components/divider/examples`); - await driver.navigate().to(`${domain}/components/flipper/examples`); - await driver.navigate().to(`${domain}/components/heading/examples`); - await driver.navigate().to(`${domain}/components/hypertext/examples`); - await driver.navigate().to(`${domain}/components/image/examples`); - await driver.navigate().to(`${domain}/components/label/examples`); - await driver.navigate().to(`${domain}/components/metatext/examples`); - await driver.navigate().to(`${domain}/components/paragraph/examples`); - await driver.navigate().to(`${domain}/components/subheading/examples`); - await driver.navigate().to(`${domain}/components/text-field/examples`); - await driver.navigate().to(`${domain}/components/toggle/examples`); - await driver.navigate().to(`${domain}/components/typography/examples`); - } finally { - await driver.quit(); - } - }); - }); -} - -/** - * Run tests on the current branch and use the branch name as the unique identifier on Sauce Labs - */ -new Promise(function (resolve, reject) { - const git = spawn("git", ["rev-parse", "--abbrev-ref", "HEAD"]); - - git.stdout.on("data", data => { - resolve(`${data}`.trim()); - }); - git.stderr.on("data", data => { - reject("Unable to get branch name", data); - }); -}).then(function (branchName) { - test(branchName); -}); diff --git a/build/transform-fragments.js b/build/transform-fragments.js index e3f5f608903..e98a91f2c74 100644 --- a/build/transform-fragments.js +++ b/build/transform-fragments.js @@ -1,49 +1,34 @@ -const onlySpace = /^\s+$/g; -const spaceBetforeTagClose = /\s+(>)/g; -const spaceBetweenTags = /(>)\s+(<)/g; -const spaceBetweenAttrs = /(["'\w])(?!\s*>)\s+/g; -const openEnded = /(?:[^="'\w])?(["'\w])\s*$/g; - +/** + * Reduces extra spaces in HTML tagged templates. + * + * @param {string} data - the fragment value + * @returns string + */ export function transformHTMLFragment(data) { - // if the chunk is only space, collapse and return it - if (data.match(onlySpace)) { - return data.replace(onlySpace, " "); - } - - // remove space before tag close - data = data.replace(spaceBetforeTagClose, "$1"); - - // remove space between tags - data = data.replace(spaceBetweenTags, "$1$2"); - - // remove space between attributes - data = data.replace(spaceBetweenAttrs, "$1 "); - - if (data.match(openEnded)) { - return data.trimStart(); - } - - return data.trim(); + data = data.replace(/\s*([<>])\s*/g, "$1"); // remove spaces before and after angle brackets + return data.replace(/\s{2,}/g, " "); // Collapse all sequences to 1 space } -const newlines = /\n/g; -const separators = /\s*([\{\};])\s*/g; -const lastProp = /;\s*(\})/g; -const extraSpaces = /\s\s+/g; -const endingSpaces = / ?\s+$/g; - +/** + * Reduces extra spaces in CSS tagged templates. + * + * Breakdown of this regex: + * (?:\s*\/\*(?:[\s\S])+?\*\/\s*) Remove comments (non-capturing) + * (?:;)\s+(?=\}) Remove semicolons and spaces followed by property list end (non-capturing) + * \s+(?=\{) Remove spaces before property list start (non-capturing) + * (?<=:)\s+ Remove spaces after property declarations (non-capturing) + * \s*([{};,])\s* Remove extra spaces before and after braces, semicolons, and commas (captures) + * + * @param {string} data - the fragment value + * @returns string + */ export function transformCSSFragment(data) { - // newlines - data = data.replace(newlines, ""); - - // Remove extra space, but not too much - data = data.replace(separators, "$1"); - - // Remove semicolons followed by property list end - data = data.replace(lastProp, "$1"); - - // space might be between property values or between selectors - data = data.replace(endingSpaces, " "); + if (/\/\*(?![\s\S]*\*\/)[\s\S]*/g.test(data)) { + throw new Error("Unterminated comment found in CSS tagged template literal"); + } - return data.replace(extraSpaces, " "); + return data.replace( + /(?:\s*\/\*(?:[\s\S])+?\*\/\s*)|(?:;)\s+(?=\})|\s+(?=\{)|(?<=:)\s+|\s*([{};,])\s*/g, + "$1" + ); } diff --git a/change/@microsoft-fast-element-065d2f58-8e71-46cb-8b0b-7c73b42483eb.json b/change/@microsoft-fast-element-065d2f58-8e71-46cb-8b0b-7c73b42483eb.json new file mode 100644 index 00000000000..0fcbb11a3da --- /dev/null +++ b/change/@microsoft-fast-element-065d2f58-8e71-46cb-8b0b-7c73b42483eb.json @@ -0,0 +1,7 @@ +{ + "type": "patch", + "comment": "chore: enable verbatimModuleSyntax to identify type-only imports and exports", + "packageName": "@microsoft/fast-element", + "email": "863023+radium-v@users.noreply.github.com", + "dependentChangeType": "none" +} diff --git a/change/@microsoft-fast-element-14a48159-ba5e-4d96-ac70-f5972b5a97a3.json b/change/@microsoft-fast-element-14a48159-ba5e-4d96-ac70-f5972b5a97a3.json new file mode 100644 index 00000000000..8fcb930db63 --- /dev/null +++ b/change/@microsoft-fast-element-14a48159-ba5e-4d96-ac70-f5972b5a97a3.json @@ -0,0 +1,7 @@ +{ + "type": "none", + "comment": "chore: remove benchmark scripts and related utilities from fast-element package", + "packageName": "@microsoft/fast-element", + "email": "863023+radium-v@users.noreply.github.com", + "dependentChangeType": "none" +} diff --git a/change/@microsoft-fast-element-4c6fc434-3a41-43ce-aab8-db1356d9d239.json b/change/@microsoft-fast-element-4c6fc434-3a41-43ce-aab8-db1356d9d239.json new file mode 100644 index 00000000000..249533f11ac --- /dev/null +++ b/change/@microsoft-fast-element-4c6fc434-3a41-43ce-aab8-db1356d9d239.json @@ -0,0 +1,7 @@ +{ + "type": "minor", + "comment": "feat: pass source element to hydration lifecycle callbacks", + "packageName": "@microsoft/fast-element", + "email": "863023+radium-v@users.noreply.github.com", + "dependentChangeType": "none" +} diff --git a/change/@microsoft-fast-element-883d6e16-fd99-4a0d-88e3-4534ba860645.json b/change/@microsoft-fast-element-883d6e16-fd99-4a0d-88e3-4534ba860645.json new file mode 100644 index 00000000000..e679f3ab4e8 --- /dev/null +++ b/change/@microsoft-fast-element-883d6e16-fd99-4a0d-88e3-4534ba860645.json @@ -0,0 +1,7 @@ +{ + "type": "none", + "comment": "introduce playwright for testing", + "packageName": "@microsoft/fast-element", + "email": "machi@microsoft.com", + "dependentChangeType": "none" +} diff --git a/change/@microsoft-fast-html-0c739bb4-dc21-4a31-b633-91f6cae9e106.json b/change/@microsoft-fast-html-0c739bb4-dc21-4a31-b633-91f6cae9e106.json new file mode 100644 index 00000000000..efa07d4bd7c --- /dev/null +++ b/change/@microsoft-fast-html-0c739bb4-dc21-4a31-b633-91f6cae9e106.json @@ -0,0 +1,7 @@ +{ + "type": "prerelease", + "comment": "test: update test fixtures for source-based lifecycle callbacks", + "packageName": "@microsoft/fast-html", + "email": "863023+radium-v@users.noreply.github.com", + "dependentChangeType": "none" +} diff --git a/change/@microsoft-fast-ssr-32cb750f-a06e-4c59-ae40-65c7ced5f9a3.json b/change/@microsoft-fast-ssr-32cb750f-a06e-4c59-ae40-65c7ced5f9a3.json new file mode 100644 index 00000000000..815227111b4 --- /dev/null +++ b/change/@microsoft-fast-ssr-32cb750f-a06e-4c59-ae40-65c7ced5f9a3.json @@ -0,0 +1,7 @@ +{ + "type": "none", + "comment": "Remove foundation as a dependency", + "packageName": "@microsoft/fast-ssr", + "email": "7559015+janechu@users.noreply.github.com", + "dependentChangeType": "none" +} diff --git a/change/@microsoft-fast-ssr-8b5e2b0b-fb26-4859-8dd9-4639a2c403e7.json b/change/@microsoft-fast-ssr-8b5e2b0b-fb26-4859-8dd9-4639a2c403e7.json new file mode 100644 index 00000000000..ef14a247a95 --- /dev/null +++ b/change/@microsoft-fast-ssr-8b5e2b0b-fb26-4859-8dd9-4639a2c403e7.json @@ -0,0 +1,7 @@ +{ + "type": "prerelease", + "comment": "chore: add @types/parse5 as a dev dependency", + "packageName": "@microsoft/fast-ssr", + "email": "863023+radium-v@users.noreply.github.com", + "dependentChangeType": "none" +} diff --git a/examples/site-rebrand-tutorial/CompanyPage/css/style.css b/examples/site-rebrand-tutorial/CompanyPage/css/style.css deleted file mode 100644 index 05022bea63d..00000000000 --- a/examples/site-rebrand-tutorial/CompanyPage/css/style.css +++ /dev/null @@ -1,478 +0,0 @@ -*, *::before, *::after { - box-sizing: border-box; -} - -body { - margin: 0; - font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, "Noto Sans", sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol", "Noto Color Emoji"; - font-size: 1rem; - font-weight: 400; - line-height: 1.5; - color: #c4cad1; - text-align: left; - background: #2A2A2A; -} - -footer { - padding-bottom: 3rem; -} - -/* hero styles */ - -.hero { - background-image: linear-gradient(rgba(0, 0, 0, 0.5), rgba(0, 0, 0, 0.5)), url("../img/kenny-luo-YLzVT6NASc4-unsplash.jpg"); - background-size: cover; - background-position: center; - width: 100wh; - height: 60vh; - min-height: 250px; - display: flex; - margin-bottom: 5rem;; -} - -.hero-text { - background-color: #2A2A2A; - width: 400px; - display: flex; - flex-direction: column; - text-align: right; - margin: auto; - padding: 2rem; -} - -button.cta { - padding: 10px 20px; - color: rgba(255, 255, 255, 0.8); - background-color: #28a745; - border-width: 0; - line-height: 1.4; -} - -button.cta:hover { - color: rgba(255, 255, 255, 1); - box-shadow: 0 5px 15px rgba(3, 80, 20, 0.4); -} - -.emphasize { - font-size: 1.25rem; -} - -/* nav bar styles */ - -.bg-dark { - background-color: #343a40; -} - -.navbar-expand-md { - flex-flow: row nowrap; - justify-content: flex-start; -} - -.navbar { - position: relative; - display: flex; - flex-wrap: wrap; - align-items: center; - justify-content: space-between; - padding: 0.5rem 1rem; -} - -.navbar .active a { - color: white!important; -} - -.navbar-nav { - display: -ms-flexbox; - display: flex; - -ms-flex-direction: column; - flex-direction: column; - padding-left: 0; - margin-bottom: 0; - list-style: none; -} - -.navbar-collapse { - -ms-flex-preferred-size: 100%; - flex-basis: 100%; - -ms-flex-positive: 1; - flex-grow: 1; - -ms-flex-align: center; - align-items: center; -} - -.navbar-dark .navbar-nav .nav-link { - color: rgba(255, 255, 255, 0.5); -} - -.navbar-dark .navbar-brand { - color: #fff; -} - -.navbar-brand { - display: inline-block; - padding-top: 0.3125rem; - padding-bottom: 0.3125rem; - margin-right: 1rem; - font-size: 1.25rem; - line-height: inherit; - white-space: nowrap; -} - -a { - color: #28a745; - text-decoration: none; - background-color: transparent; -} - -.navbar-expand-md .navbar-collapse { - display: -ms-flexbox !important; - display: flex !important; - -ms-flex-preferred-size: auto; - flex-basis: auto; -} - -.navbar-expand-md .navbar-nav { - -ms-flex-direction: row; - flex-direction: row; -} - -.mr-auto, .mx-auto { - margin-right: auto !important; -} - -ol, ul, dl { - margin-top: 0; - margin-bottom: 1rem; -} - -.nav-link { - display: block; - padding: 0.5rem 1rem; -} -.navbar-dark .navbar-nav .nav-link:hover, .navbar-dark .navbar-nav .nav-link:focus { - color: rgba(255, 255, 255, 0.75); -} -/* form in navbar */ -.mt-md-0, .my-md-0 { - margin-top: 0!important; -} -.mt-2, .my-2 { - margin-top: .5rem!important; -} -.form-inline { - display: -webkit-box; - display: -ms-flexbox; - display: flex; - -webkit-box-orient: horizontal; - -webkit-box-direction: normal; - -ms-flex-flow: row wrap; - flex-flow: row wrap; - -webkit-box-align: center; - -ms-flex-align: center; - align-items: center; -} - -.form-control { - display: block; - width: 100%; - padding: .375rem .75rem; - font-size: 1rem; - line-height: 1.5; - color: #495057; - background-color: white; - background-clip: padding-box; - border: 1px solid grey; - transition: border-color .15s ease-in-out,box-shadow .15s ease-in-out; -} -.form-inline .form-control { - display: inline-block; - width: auto; - vertical-align: middle; -} -button, input { - overflow: visible; -} -button, input, optgroup, select, textarea { - margin: 0; - font-family: inherit; - font-size: inherit; - line-height: inherit; -} - -.fixed-top { - position: fixed; - top: 0; - right: 0; - left: 0; - z-index: 1000; -} - -.btn { - display: inline-block; - font-weight: 400; - text-align: center; - white-space: nowrap; - vertical-align: middle; - -webkit-user-select: none; - -moz-user-select: none; - -ms-user-select: none; - user-select: none; - border: 1px solid transparent; - padding: .375rem .75rem; - font-size: 1rem; - line-height: 1.5; - transition: color .15s ease-in-out, background-color .15s ease-in-out, border-color .15s ease-in-out, box-shadow .15s ease-in-out; -} - -.btn-outline-success { - color: #28a745; - background-color: transparent; - background-image: none; - border-color: #28a745; -} -.btn-outline-success:hover { - color: #fff; - background-color: #28a745; - border-color: #28a745; -} - -.btn:not(:disabled):not(.disabled) { - cursor: pointer; -} -.mt-2, .my-2 { - margin-top: .5rem!important; -} -.mb-2, .my-2 { - margin-bottom: .5rem!important; -} -.mt-sm-0, .my-sm-0 { - margin-top: 0!important; -} -.mb-sm-0, .my-sm-0 { - margin-bottom: 0!important; -} -.mr-sm-2, .mx-sm-2 { - margin-right: .5rem!important; -} - -/* three column headings */ -.container { - width: 100%; - padding-right: 15px; - padding-left: 15px; - margin-right: auto; - margin-left: auto; - max-width: 1140px; /* comes from media queries in source */ -} - -.row { - display: -ms-flexbox; - display: flex; - -ms-flex-wrap: wrap; - flex-wrap: wrap; - margin-right: -15px; - margin-left: -15px; -} - -.col-1, .col-2, .col-3, .col-4, .col-5, .col-6, .col-7, .col-8, .col-9, .col-10, .col-11, .col-12, .col, .col-auto, .col-sm-1, .col-sm-2, .col-sm-3, .col-sm-4, .col-sm-5, .col-sm-6, .col-sm-7, .col-sm-8, .col-sm-9, .col-sm-10, .col-sm-11, .col-sm-12, .col-sm, .col-sm-auto, .col-md-1, .col-md-2, .col-md-3, .col-md-4, .col-md-5, .col-md-6, .col-md-7, .col-md-8, .col-md-9, .col-md-10, .col-md-11, .col-md-12, .col-md, .col-md-auto, .col-lg-1, .col-lg-2, .col-lg-3, .col-lg-4, .col-lg-5, .col-lg-6, .col-lg-7, .col-lg-8, .col-lg-9, .col-lg-10, .col-lg-11, .col-lg-12, .col-lg, .col-lg-auto, .col-xl-1, .col-xl-2, .col-xl-3, .col-xl-4, .col-xl-5, .col-xl-6, .col-xl-7, .col-xl-8, .col-xl-9, .col-xl-10, .col-xl-11, .col-xl-12, .col-xl, .col-xl-auto { - position: relative; - width: 100%; - padding-right: 15px; - padding-left: 15px; -} -@media (min-width: 768px) { - .col-md-5 { - -ms-flex: 0 0 41.666667%; - flex: 0 0 41.666667%; - max-width: 41.666667%; - } -} -@media (min-width: 768px) { - .col-md-6 { - -ms-flex: 0 0 50%; - flex: 0 0 50%; - max-width: 50%; - } -} -.col-md-8 { - -ms-flex: 0 0 66.666667%; - flex: 0 0 66.666667%; - max-width: 66.666667%; -} - -.summary .col-lg-4 { - margin-bottom: 1.5rem; - text-align: center; -} - -.col-lg-4 { - -ms-flex: 0 0 33.333333%; - flex: 0 0 33.333333%; - max-width: 33.333333%; - -} - -.rounded-circle { - border-radius: 50% !important; -} -img { - vertical-align: middle; - border-style: none; -} -.img-fluid { - max-width: 100%; - height: auto; -} - -.summary h2 { - font-weight: 400; -} - -h1, h2, h3, h4, h5, h6, .h1, .h2, .h3, .h4, .h5, .h6 { - margin-bottom: 0.5rem; - font-weight: 500; - line-height: 1.2; -} -h1, h2, h3, h4, h5, h6 { - margin-top: 0; - margin-bottom: 0.5rem; -} - -.summary .col-lg-4 p { - margin-right: .75rem; - margin-left: .75rem; -} -p { - margin-top: 0; - margin-bottom: 1rem; -} -.btn-secondary { - color: white!important; - background-color: transparent; - border-color: #e1477e; -} - -/* featurettes */ -.col-md-7 { - -ms-flex: 0 0 58.333333%; - flex: 0 0 58.333333%; - max-width: 58.333333%; -} - -.summary h2 { - font-weight: 400; -} - -.featurette-heading { - font-weight: 300; - line-height: 1; - letter-spacing: -.05rem; -} -.lead { - font-size: 1.25rem; - font-weight: 300; -} - -.featurette-divider { - margin: 5rem 0; -} - -.order-md-2 { - -ms-flex-order: 2; - order: 2; -} - -/* footer */ - -.offset-md-2 { - margin-left: 16.666667%; -} -h4, .h4 { - font-size: 1.5rem; -} -.mb-3, .my-3 { - margin-bottom: 1rem !important; -} -.footer-divider { - margin: 2rem 0; -} -.input-group { - position: relative; - display: -webkit-box; - display: -ms-flexbox; - display: flex; - -ms-flex-wrap: wrap; - flex-wrap: wrap; - -webkit-box-align: stretch; - -ms-flex-align: stretch; - align-items: stretch; - width: 100%; -} -.input-group-prepend { - margin-right: -1px; -} -.input-group-append, .input-group-prepend { - display: -webkit-box; - display: -ms-flexbox; - display: flex; -} -.input-group-text { - display: -webkit-box; - display: -ms-flexbox; - display: flex; - -webkit-box-align: center; - -ms-flex-align: center; - align-items: center; - padding: .375rem .75rem; - margin-bottom: 0; - font-size: 1rem; - font-weight: 400; - line-height: 1.5; - color: #495057; - text-align: center; - white-space: nowrap; - background-color: white; - border: 1px solid grey; -} - -.input-group>.custom-file, .input-group>.custom-select, .input-group>.form-control { - position: relative; - -webkit-box-flex: 1; - -ms-flex: 1 1 auto; - flex: 1 1 auto; - width: 1%; - margin-bottom: 0; -} -.input-group>.input-group-append:last-child>.btn:not(:last-child):not(.dropdown-toggle), .input-group>.input-group-append:last-child>.input-group-text:not(:last-child), .input-group>.input-group-append:not(:last-child)>.btn, .input-group>.input-group-append:not(:last-child)>.input-group-text, .input-group>.input-group-prepend>.btn, .input-group>.input-group-prepend>.input-group-text { - border-top-right-radius: 0; - border-bottom-right-radius: 0; -} - -label { - display: inline-block; - margin-bottom: 0.5rem; -} - -.float-right { - float: right!important; -} - -.disabled_username { - cursor: not-allowed; - opacity: 50%; -} - -.text-muted { - color: #6c757d !important; -} - -h2, .h2 { - font-size: 2rem; -} - -.featurette-heading { - font-size: 50px; - margin-top: 7rem; -} - -/* Add the CSS needed for the new FAST design system */ diff --git a/examples/site-rebrand-tutorial/CompanyPage/img/aw-creative-RUoucfLlS7k-unsplash.jpg b/examples/site-rebrand-tutorial/CompanyPage/img/aw-creative-RUoucfLlS7k-unsplash.jpg deleted file mode 100644 index 8fa7fc95236..00000000000 Binary files a/examples/site-rebrand-tutorial/CompanyPage/img/aw-creative-RUoucfLlS7k-unsplash.jpg and /dev/null differ diff --git a/examples/site-rebrand-tutorial/CompanyPage/img/greg-nunes-hmzKoapQuYY-unsplash.jpg b/examples/site-rebrand-tutorial/CompanyPage/img/greg-nunes-hmzKoapQuYY-unsplash.jpg deleted file mode 100644 index abe12b1b93f..00000000000 Binary files a/examples/site-rebrand-tutorial/CompanyPage/img/greg-nunes-hmzKoapQuYY-unsplash.jpg and /dev/null differ diff --git a/examples/site-rebrand-tutorial/CompanyPage/img/holger-link-GYgozuJY4D8-unsplash.jpg b/examples/site-rebrand-tutorial/CompanyPage/img/holger-link-GYgozuJY4D8-unsplash.jpg deleted file mode 100644 index a67ae681529..00000000000 Binary files a/examples/site-rebrand-tutorial/CompanyPage/img/holger-link-GYgozuJY4D8-unsplash.jpg and /dev/null differ diff --git a/examples/site-rebrand-tutorial/CompanyPage/img/kenny-luo-YLzVT6NASc4-unsplash.jpg b/examples/site-rebrand-tutorial/CompanyPage/img/kenny-luo-YLzVT6NASc4-unsplash.jpg deleted file mode 100644 index fc8742ed033..00000000000 Binary files a/examples/site-rebrand-tutorial/CompanyPage/img/kenny-luo-YLzVT6NASc4-unsplash.jpg and /dev/null differ diff --git a/examples/site-rebrand-tutorial/CompanyPage/img/left-arrow.svg b/examples/site-rebrand-tutorial/CompanyPage/img/left-arrow.svg deleted file mode 100644 index eeac0ce59ac..00000000000 --- a/examples/site-rebrand-tutorial/CompanyPage/img/left-arrow.svg +++ /dev/null @@ -1,43 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/examples/site-rebrand-tutorial/CompanyPage/img/markus-spiske-80BnaHKhKuQ-unsplash.jpg b/examples/site-rebrand-tutorial/CompanyPage/img/markus-spiske-80BnaHKhKuQ-unsplash.jpg deleted file mode 100644 index d13bf8ac09f..00000000000 Binary files a/examples/site-rebrand-tutorial/CompanyPage/img/markus-spiske-80BnaHKhKuQ-unsplash.jpg and /dev/null differ diff --git a/examples/site-rebrand-tutorial/CompanyPage/img/markus-spiske-cn0-hgcpoL8-unsplash.jpg b/examples/site-rebrand-tutorial/CompanyPage/img/markus-spiske-cn0-hgcpoL8-unsplash.jpg deleted file mode 100644 index 5f3abcec06e..00000000000 Binary files a/examples/site-rebrand-tutorial/CompanyPage/img/markus-spiske-cn0-hgcpoL8-unsplash.jpg and /dev/null differ diff --git a/examples/site-rebrand-tutorial/CompanyPage/img/right-arrow.svg b/examples/site-rebrand-tutorial/CompanyPage/img/right-arrow.svg deleted file mode 100644 index c91f9005d57..00000000000 --- a/examples/site-rebrand-tutorial/CompanyPage/img/right-arrow.svg +++ /dev/null @@ -1,43 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/examples/site-rebrand-tutorial/CompanyPage/img/umberto-del-piano-7HXms3SCXhI-unsplash.jpg b/examples/site-rebrand-tutorial/CompanyPage/img/umberto-del-piano-7HXms3SCXhI-unsplash.jpg deleted file mode 100644 index a645e0f5555..00000000000 Binary files a/examples/site-rebrand-tutorial/CompanyPage/img/umberto-del-piano-7HXms3SCXhI-unsplash.jpg and /dev/null differ diff --git a/examples/site-rebrand-tutorial/CompanyPage/img/usgs-3F2YdXjJMCI-unsplash.jpg b/examples/site-rebrand-tutorial/CompanyPage/img/usgs-3F2YdXjJMCI-unsplash.jpg deleted file mode 100644 index c93f6e6c7ad..00000000000 Binary files a/examples/site-rebrand-tutorial/CompanyPage/img/usgs-3F2YdXjJMCI-unsplash.jpg and /dev/null differ diff --git a/examples/site-rebrand-tutorial/CompanyPage/img/waranont-joe-CJ1oBPZJFPg-unsplash.jpg b/examples/site-rebrand-tutorial/CompanyPage/img/waranont-joe-CJ1oBPZJFPg-unsplash.jpg deleted file mode 100644 index f74f569d74a..00000000000 Binary files a/examples/site-rebrand-tutorial/CompanyPage/img/waranont-joe-CJ1oBPZJFPg-unsplash.jpg and /dev/null differ diff --git a/examples/site-rebrand-tutorial/CompanyPage/index.html b/examples/site-rebrand-tutorial/CompanyPage/index.html deleted file mode 100644 index d94386ceab7..00000000000 --- a/examples/site-rebrand-tutorial/CompanyPage/index.html +++ /dev/null @@ -1,180 +0,0 @@ - - - - - - - Company Inc: Have art that lives on your wall - - - - -
- -
- -
- - - -
-
-

Start exploring

-

See how we can transform your living space into an art gallery

- - -
-
- - - -
- -
-
- Generic placeholder image -

Sea life

-

Donec sed odio dui. Etiam porta sem malesuada magna mollis euismod. Nullam id dolor id nibh ultricies - vehicula ut id elit. Morbi leo risus, porta ac consectetur ac, vestibulum at eros. Praesent commodo cursus - magna.

- -
-
- Generic placeholder image -

Walking alone

-

Duis mollis, est non commodo luctus, nisi erat porttitor ligula, eget lacinia odio sem nec elit. Cras - mattis - consectetur purus sit amet fermentum. Fusce dapibus, tellus ac cursus commodo, tortor mauris condimentum - nibh. -

- -
-
- Generic placeholder image -

Our planet

-

Donec sed odio dui. Cras justo odio, dapibus ac facilisis in, egestas eget quam. Vestibulum id ligula porta - felis euismod semper. Fusce dapibus, tellus ac cursus commodo, tortor mauris condimentum nibh.

- - -
-
- -
- - -
-
-

First featurette heading. It’ll blow your mind. -

-

Donec ullamcorper nulla non metus auctor fringilla. Vestibulum id ligula porta felis euismod - semper. Praesent commodo cursus magna, vel scelerisque nisl consectetur. Fusce dapibus, tellus ac cursus - commodo.

-
-
- -
-
-
-
-
-

Oh yeah, it’s that good. See for yourself.

-

Donec ullamcorper nulla non metus auctor fringilla. Vestibulum id ligula porta felis euismod - semper. Praesent commodo cursus magna, vel scelerisque nisl consectetur. Fusce dapibus, tellus ac cursus - commodo.

-
-
- -
-
-
-
-
-

And lastly, this one. Checkmate.

-

Donec ullamcorper nulla non metus auctor fringilla. Vestibulum id ligula porta felis euismod - semper. Praesent commodo cursus magna, vel scelerisque nisl consectetur. Fusce dapibus, tellus ac cursus - commodo.

-
-
- -
-
- -
- -
- -
-
-

Contact

-
-
-
- -
-
- -
-
-
-
-
- @ -
- -
-
-
- -
-
- - -
-
- - -
- - -
-
-
-
- - - - - \ No newline at end of file diff --git a/examples/site-rebrand-tutorial/CompanyPage/js/scroll.js b/examples/site-rebrand-tutorial/CompanyPage/js/scroll.js deleted file mode 100644 index 84a46cbdf5c..00000000000 --- a/examples/site-rebrand-tutorial/CompanyPage/js/scroll.js +++ /dev/null @@ -1,20 +0,0 @@ -const anchors = Array.from(document.querySelectorAll('a[name]')); -const xPositions = anchors.map(a => { return a.getBoundingClientRect().top + window.pageYOffset;} ); -const navItems = Array.from(document.querySelectorAll('li.nav-item')); - -document.addEventListener('scroll', e => { - const maxScroll = window.pageYOffset + window.innerHeight + 100 > document.body.scrollHeight; - - if (maxScroll) { - navItems.forEach(n => {n.classList.remove('active');}); - navItems[anchors.length - 1].classList.add('active'); - } else { - for(let i = anchors.length - 1; i >= 0; --i) { - if (window.pageYOffset + 120 > xPositions[i]) { - navItems.forEach(n => {n.classList.remove('active');}); - navItems[i].classList.add('active'); - return; - } - } - } -}); diff --git a/examples/site-rebrand-tutorial/FastPage/css/style.css b/examples/site-rebrand-tutorial/FastPage/css/style.css deleted file mode 100644 index e561a93209a..00000000000 --- a/examples/site-rebrand-tutorial/FastPage/css/style.css +++ /dev/null @@ -1,651 +0,0 @@ -*, -*::before, -*::after { - box-sizing: border-box; -} - -body { - margin: 0; - font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, - "Helvetica Neue", Arial, "Noto Sans", sans-serif, "Apple Color Emoji", - "Segoe UI Emoji", "Segoe UI Symbol", "Noto Color Emoji"; - font-size: 1rem; - font-weight: 400; - line-height: 1.5; - color: #c4cad1; - text-align: left; - background: #2a2a2a; -} - -footer { - padding-bottom: 3rem; -} - -/* hero styles */ - -.hero { - background-image: linear-gradient(rgba(0, 0, 0, 0.5), rgba(0, 0, 0, 0.5)), - url("../img/kenny-luo-YLzVT6NASc4-unsplash.jpg"); - background-size: cover; - background-position: center; - width: 100wh; - height: 60vh; - min-height: 250px; - display: flex; - margin-bottom: 5rem; -} - -.hero-text { - border-radius: calc(var(--corner-radius, 10) * 1px); - background-color: var(--background-color); - color: var(--neutral-foreground-rest); - width: 400px; - display: flex; - flex-direction: column; - text-align: right; - margin: auto; - padding: 2rem; -} - -button.cta { - padding: 10px 20px; - color: rgba(255, 255, 255, 0.8); - background-color: #28a745; - border-width: 0; - line-height: 1.4; -} - -button.cta:hover { - color: rgba(255, 255, 255, 1); - box-shadow: 0 5px 15px rgba(3, 80, 20, 0.4); -} - -.emphasize { - font-size: 1.25rem; -} - -/* nav bar styles */ - -.bg-dark { - background-color: #343a40; -} - -.navbar-expand-md { - flex-flow: row nowrap; - justify-content: flex-start; -} - -.navbar { - position: relative; - display: flex; - flex-wrap: wrap; - align-items: center; - justify-content: space-between; - padding: 0.5rem 1rem; -} - -.navbar .active a { - color: white !important; -} - -.navbar-nav { - display: -ms-flexbox; - display: flex; - -ms-flex-direction: column; - flex-direction: column; - padding-left: 0; - margin-bottom: 0; - list-style: none; -} - -.navbar-collapse { - -ms-flex-preferred-size: 100%; - flex-basis: 100%; - -ms-flex-positive: 1; - flex-grow: 1; - -ms-flex-align: center; - align-items: center; -} - -.navbar-dark .navbar-nav .nav-link { - color: rgba(255, 255, 255, 0.5); -} - -.navbar-dark .navbar-brand { - color: #fff; -} - -.navbar-brand { - display: inline-block; - padding-top: 0.3125rem; - padding-bottom: 0.3125rem; - margin-right: 1rem; - font-size: 1.25rem; - line-height: inherit; - white-space: nowrap; -} - -a { - color: #28a745; - text-decoration: none; - background-color: transparent; -} - -.navbar-expand-md .navbar-collapse { - display: -ms-flexbox !important; - display: flex !important; - -ms-flex-preferred-size: auto; - flex-basis: auto; -} - -.navbar-expand-md .navbar-nav { - -ms-flex-direction: row; - flex-direction: row; -} - -.mr-auto, -.mx-auto { - margin-right: auto !important; -} - -ol, -ul, -dl { - margin-top: 0; - margin-bottom: 1rem; -} - -.nav-link { - display: block; - padding: 0.5rem 1rem; -} -.navbar-dark .navbar-nav .nav-link:hover, -.navbar-dark .navbar-nav .nav-link:focus { - color: rgba(255, 255, 255, 0.75); -} -/* form in navbar */ -.mt-md-0, -.my-md-0 { - margin-top: 0 !important; -} -.mt-2, -.my-2 { - margin-top: 0.5rem !important; -} -.form-inline { - display: -webkit-box; - display: -ms-flexbox; - display: flex; - -webkit-box-orient: horizontal; - -webkit-box-direction: normal; - -ms-flex-flow: row wrap; - flex-flow: row wrap; - -webkit-box-align: center; - -ms-flex-align: center; - align-items: center; -} - -.form-control { - display: block; - width: 100%; - padding: 0.375rem 0.75rem; - font-size: 1rem; - line-height: 1.5; - color: #495057; - background-color: white; - background-clip: padding-box; - border: 1px solid grey; - transition: border-color 0.15s ease-in-out, box-shadow 0.15s ease-in-out; -} -.form-inline .form-control { - display: inline-block; - width: auto; - vertical-align: middle; -} -button, -input { - overflow: visible; -} -button, -input, -optgroup, -select, -textarea { - margin: 0; - font-family: inherit; - font-size: inherit; - line-height: inherit; -} - -.fixed-top { - position: fixed; - top: 0; - right: 0; - left: 0; - z-index: 1000; -} - -.btn { - display: inline-block; - font-weight: 400; - text-align: center; - white-space: nowrap; - vertical-align: middle; - -webkit-user-select: none; - -moz-user-select: none; - -ms-user-select: none; - user-select: none; - border: 1px solid transparent; - padding: 0.375rem 0.75rem; - font-size: 1rem; - line-height: 1.5; - transition: color 0.15s ease-in-out, background-color 0.15s ease-in-out, - border-color 0.15s ease-in-out, box-shadow 0.15s ease-in-out; -} - -.btn-outline-success { - color: #28a745; - background-color: transparent; - background-image: none; - border-color: #28a745; -} -.btn-outline-success:hover { - color: #fff; - background-color: #28a745; - border-color: #28a745; -} - -.btn:not(:disabled):not(.disabled) { - cursor: pointer; -} -.mt-2, -.my-2 { - margin-top: 0.5rem !important; -} -.mb-2, -.my-2 { - margin-bottom: 0.5rem !important; -} -.mt-sm-0, -.my-sm-0 { - margin-top: 0 !important; -} -.mb-sm-0, -.my-sm-0 { - margin-bottom: 0 !important; -} -.mr-sm-2, -.mx-sm-2 { - margin-right: 0.5rem !important; -} - -/* three column headings */ -.container { - width: 100%; - padding-right: 15px; - padding-left: 15px; - margin-right: auto; - margin-left: auto; - max-width: 1140px; /* comes from media queries in source */ -} - -.row { - display: -ms-flexbox; - display: flex; - -ms-flex-wrap: wrap; - flex-wrap: wrap; - margin-right: -15px; - margin-left: -15px; -} - -.col-1, -.col-2, -.col-3, -.col-4, -.col-5, -.col-6, -.col-7, -.col-8, -.col-9, -.col-10, -.col-11, -.col-12, -.col, -.col-auto, -.col-sm-1, -.col-sm-2, -.col-sm-3, -.col-sm-4, -.col-sm-5, -.col-sm-6, -.col-sm-7, -.col-sm-8, -.col-sm-9, -.col-sm-10, -.col-sm-11, -.col-sm-12, -.col-sm, -.col-sm-auto, -.col-md-1, -.col-md-2, -.col-md-3, -.col-md-4, -.col-md-5, -.col-md-6, -.col-md-7, -.col-md-8, -.col-md-9, -.col-md-10, -.col-md-11, -.col-md-12, -.col-md, -.col-md-auto, -.col-lg-1, -.col-lg-2, -.col-lg-3, -.col-lg-4, -.col-lg-5, -.col-lg-6, -.col-lg-7, -.col-lg-8, -.col-lg-9, -.col-lg-10, -.col-lg-11, -.col-lg-12, -.col-lg, -.col-lg-auto, -.col-xl-1, -.col-xl-2, -.col-xl-3, -.col-xl-4, -.col-xl-5, -.col-xl-6, -.col-xl-7, -.col-xl-8, -.col-xl-9, -.col-xl-10, -.col-xl-11, -.col-xl-12, -.col-xl, -.col-xl-auto { - position: relative; - width: 100%; - padding-right: 15px; - padding-left: 15px; -} -@media (min-width: 768px) { - .col-md-5 { - -ms-flex: 0 0 41.666667%; - flex: 0 0 41.666667%; - max-width: 41.666667%; - } -} -@media (min-width: 768px) { - .col-md-6 { - -ms-flex: 0 0 50%; - flex: 0 0 50%; - max-width: 50%; - } -} -.col-md-8 { - -ms-flex: 0 0 66.666667%; - flex: 0 0 66.666667%; - max-width: 66.666667%; -} - -.summary .col-lg-4 { - margin-bottom: 1.5rem; - text-align: center; -} - -.col-lg-4 { - -ms-flex: 0 0 33.333333%; - flex: 0 0 33.333333%; - max-width: 33.333333%; -} - -.rounded-circle { - border-radius: 50% !important; -} -img { - vertical-align: middle; - border-style: none; -} -.img-fluid { - max-width: 100%; - height: auto; -} - -h1, -h2, -h3, -h4, -h5, -h6, -.h1, -.h2, -.h3, -.h4, -.h5, -.h6 { - margin-bottom: 0.5rem; - font-weight: 500; - line-height: 1.2; -} -h1, -h2, -h3, -h4, -h5, -h6 { - margin-top: 0; - margin-bottom: 0.5rem; -} - -.summary .col-lg-4 p { - margin-right: 0.75rem; - margin-left: 0.75rem; -} - -.btn-secondary { - color: white !important; - background-color: transparent; - border-color: #e1477e; -} - -/* featurettes */ -.col-md-7 { - -ms-flex: 0 0 58.333333%; - flex: 0 0 58.333333%; - max-width: 58.333333%; -} - -.summary h2 { - font-weight: 400; -} - -.featurette-heading { - font-weight: 300; - line-height: 1; - letter-spacing: -0.05rem; -} -.lead { - font-size: 1.25rem; - font-weight: 300; -} - -.featurette-divider { - margin: 5rem 0; -} - -.order-md-2 { - -ms-flex-order: 2; - order: 2; -} - -/* footer */ - -.offset-md-2 { - margin-left: 16.666667%; -} -h4, -.h4 { - font-size: 1.5rem; -} -.mb-3, -.my-3 { - margin-bottom: 1rem !important; -} -.footer-divider { - margin: 2rem 0; -} -.input-group { - position: relative; - display: -webkit-box; - display: -ms-flexbox; - display: flex; - -ms-flex-wrap: wrap; - flex-wrap: wrap; - -webkit-box-align: stretch; - -ms-flex-align: stretch; - align-items: stretch; - width: 100%; -} -.input-group-prepend { - margin-right: -1px; -} -.input-group-append, -.input-group-prepend { - display: -webkit-box; - display: -ms-flexbox; - display: flex; -} -.input-group-text { - display: -webkit-box; - display: -ms-flexbox; - display: flex; - -webkit-box-align: center; - -ms-flex-align: center; - align-items: center; - padding: 0.375rem 0.75rem; - margin-bottom: 0; - font-size: 1rem; - font-weight: 400; - line-height: 1.5; - color: #495057; - text-align: center; - white-space: nowrap; - background-color: white; - border: 1px solid grey; -} - -.input-group > .custom-file, -.input-group > .custom-select, -.input-group > .form-control { - position: relative; - -webkit-box-flex: 1; - -ms-flex: 1 1 auto; - flex: 1 1 auto; - width: 1%; - margin-bottom: 0; -} -.input-group - > .input-group-append:last-child - > .btn:not(:last-child):not(.dropdown-toggle), -.input-group - > .input-group-append:last-child - > .input-group-text:not(:last-child), -.input-group > .input-group-append:not(:last-child) > .btn, -.input-group > .input-group-append:not(:last-child) > .input-group-text, -.input-group > .input-group-prepend > .btn, -.input-group > .input-group-prepend > .input-group-text { - border-top-right-radius: 0; - border-bottom-right-radius: 0; -} - -label { - display: inline-block; - margin-bottom: 0.5rem; -} - -.float-right { - float: right !important; -} - -.disabled_username { - cursor: not-allowed; - opacity: 50%; -} - -.text-muted { - color: var(--neutral-foreground-hint); -} - -.summary h2 { - font-weight: 400; -} - -h2, -.h2 { - font-size: var(--type-ramp-plus-4-font-size); - line-height: var(--type-ramp-plus-4-line-height); -} - -.featurette-heading { - font-size: var(--type-ramp-plus-6-font-size); - margin-top: 7rem; -} - -/* Add the CSS needed for the new FAST design system */ -fast-text-field { - width: 100%; -} - -#search { - padding-right: 10px; - width: calc(100% - 70px); - margin-top: -4px; -} - -#message { - width: 100%; - height: 150px; -} - -#message::part(control) { - width: 100%; - height: 100%; -} - -#at { - width: 35px; -} -#username { - width: calc(100% - 35px); -} - -#designPalletteOn { - --card-width: 300px; - padding: 2em; - margin: 1em; - position: sticky; - top: 80px; - z-index: 999; - float: left; -} - -#designPalletteOff { - --card-width: 180px; - padding: 0.5em; - margin: 0.5em; - position: sticky; - top: 80px; - z-index: 999; - float: left; - display: none; -} - -.call-to-action::part(control) { - font-size: var(--type-ramp-plus-2-font-size); - line-height: var(--type-ramp-plus-2-line-height); -} \ No newline at end of file diff --git a/examples/site-rebrand-tutorial/FastPage/img/aw-creative-RUoucfLlS7k-unsplash.jpg b/examples/site-rebrand-tutorial/FastPage/img/aw-creative-RUoucfLlS7k-unsplash.jpg deleted file mode 100644 index 8fa7fc95236..00000000000 Binary files a/examples/site-rebrand-tutorial/FastPage/img/aw-creative-RUoucfLlS7k-unsplash.jpg and /dev/null differ diff --git a/examples/site-rebrand-tutorial/FastPage/img/greg-nunes-hmzKoapQuYY-unsplash.jpg b/examples/site-rebrand-tutorial/FastPage/img/greg-nunes-hmzKoapQuYY-unsplash.jpg deleted file mode 100644 index abe12b1b93f..00000000000 Binary files a/examples/site-rebrand-tutorial/FastPage/img/greg-nunes-hmzKoapQuYY-unsplash.jpg and /dev/null differ diff --git a/examples/site-rebrand-tutorial/FastPage/img/holger-link-GYgozuJY4D8-unsplash.jpg b/examples/site-rebrand-tutorial/FastPage/img/holger-link-GYgozuJY4D8-unsplash.jpg deleted file mode 100644 index a67ae681529..00000000000 Binary files a/examples/site-rebrand-tutorial/FastPage/img/holger-link-GYgozuJY4D8-unsplash.jpg and /dev/null differ diff --git a/examples/site-rebrand-tutorial/FastPage/img/kenny-luo-YLzVT6NASc4-unsplash.jpg b/examples/site-rebrand-tutorial/FastPage/img/kenny-luo-YLzVT6NASc4-unsplash.jpg deleted file mode 100644 index fc8742ed033..00000000000 Binary files a/examples/site-rebrand-tutorial/FastPage/img/kenny-luo-YLzVT6NASc4-unsplash.jpg and /dev/null differ diff --git a/examples/site-rebrand-tutorial/FastPage/img/left-arrow.svg b/examples/site-rebrand-tutorial/FastPage/img/left-arrow.svg deleted file mode 100644 index eeac0ce59ac..00000000000 --- a/examples/site-rebrand-tutorial/FastPage/img/left-arrow.svg +++ /dev/null @@ -1,43 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/examples/site-rebrand-tutorial/FastPage/img/markus-spiske-80BnaHKhKuQ-unsplash.jpg b/examples/site-rebrand-tutorial/FastPage/img/markus-spiske-80BnaHKhKuQ-unsplash.jpg deleted file mode 100644 index d13bf8ac09f..00000000000 Binary files a/examples/site-rebrand-tutorial/FastPage/img/markus-spiske-80BnaHKhKuQ-unsplash.jpg and /dev/null differ diff --git a/examples/site-rebrand-tutorial/FastPage/img/markus-spiske-cn0-hgcpoL8-unsplash.jpg b/examples/site-rebrand-tutorial/FastPage/img/markus-spiske-cn0-hgcpoL8-unsplash.jpg deleted file mode 100644 index 5f3abcec06e..00000000000 Binary files a/examples/site-rebrand-tutorial/FastPage/img/markus-spiske-cn0-hgcpoL8-unsplash.jpg and /dev/null differ diff --git a/examples/site-rebrand-tutorial/FastPage/img/right-arrow.svg b/examples/site-rebrand-tutorial/FastPage/img/right-arrow.svg deleted file mode 100644 index c91f9005d57..00000000000 --- a/examples/site-rebrand-tutorial/FastPage/img/right-arrow.svg +++ /dev/null @@ -1,43 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/examples/site-rebrand-tutorial/FastPage/img/umberto-del-piano-7HXms3SCXhI-unsplash.jpg b/examples/site-rebrand-tutorial/FastPage/img/umberto-del-piano-7HXms3SCXhI-unsplash.jpg deleted file mode 100644 index a645e0f5555..00000000000 Binary files a/examples/site-rebrand-tutorial/FastPage/img/umberto-del-piano-7HXms3SCXhI-unsplash.jpg and /dev/null differ diff --git a/examples/site-rebrand-tutorial/FastPage/img/usgs-3F2YdXjJMCI-unsplash.jpg b/examples/site-rebrand-tutorial/FastPage/img/usgs-3F2YdXjJMCI-unsplash.jpg deleted file mode 100644 index c93f6e6c7ad..00000000000 Binary files a/examples/site-rebrand-tutorial/FastPage/img/usgs-3F2YdXjJMCI-unsplash.jpg and /dev/null differ diff --git a/examples/site-rebrand-tutorial/FastPage/img/waranont-joe-CJ1oBPZJFPg-unsplash.jpg b/examples/site-rebrand-tutorial/FastPage/img/waranont-joe-CJ1oBPZJFPg-unsplash.jpg deleted file mode 100644 index f74f569d74a..00000000000 Binary files a/examples/site-rebrand-tutorial/FastPage/img/waranont-joe-CJ1oBPZJFPg-unsplash.jpg and /dev/null differ diff --git a/examples/site-rebrand-tutorial/FastPage/index.html b/examples/site-rebrand-tutorial/FastPage/index.html deleted file mode 100644 index d061417604c..00000000000 --- a/examples/site-rebrand-tutorial/FastPage/index.html +++ /dev/null @@ -1,355 +0,0 @@ - - - - - - - Company Inc: Have art that lives on your wall - - - - - -
- -
- -
- - - -
-
-

Start exploring

-

See how we can transform your living space into an art gallery

- Browse gallery -
-
- - - - - -
Design System Properties
-

cornerRadius: px - - - 0px - - - 50px - - -

-
-

disabledOpacity: % - - - 0% - - - 100% - - -

-
-

baseLayerLuminance: - - - Black - - - Dark - - - Light - - -

-
-

-
- designUnit: - density: - baseHeightMultiplier: - baseHorizontalSpacingMultiplier: - - outlineWidth: - -
- - Controls  - Hide - Show - -
- - - - - Controls  - Hide - Show - - - -
- -
-
- Generic placeholder image -

Sea life

-

Donec sed odio dui. Etiam porta sem malesuada magna mollis euismod. Nullam id dolor id nibh ultricies - vehicula ut id elit. Morbi leo risus, porta ac consectetur ac, vestibulum at eros. Praesent commodo cursus - magna.

- View details » -
-
- Generic placeholder image -

Walking alone

-

Duis mollis, est non commodo luctus, nisi erat porttitor ligula, eget lacinia odio sem nec elit. Cras - mattis - consectetur purus sit amet fermentum. Fusce dapibus, tellus ac cursus commodo, tortor mauris condimentum - nibh. -

- View details » -
-
- Generic placeholder image -

Our planet

-

Donec sed odio dui. Cras justo odio, dapibus ac facilisis in, egestas eget quam. Vestibulum id ligula - porta - felis euismod semper. Fusce dapibus, tellus ac cursus commodo, tortor mauris condimentum nibh.

- - View details » -
-
- - - - -
-
-

First featurette heading. It’ll blow your - mind. -

-

Donec ullamcorper nulla non metus auctor fringilla. Vestibulum id ligula porta felis euismod - semper. Praesent commodo cursus magna, vel scelerisque nisl consectetur. Fusce dapibus, tellus ac cursus - commodo.

-
-
- -
-
- -
-
-

Oh yeah, it’s that good. See for yourself. -

-

Donec ullamcorper nulla non metus auctor fringilla. Vestibulum id ligula porta felis euismod - semper. Praesent commodo cursus magna, vel scelerisque nisl consectetur. Fusce dapibus, tellus ac cursus - commodo.

-
-
- -
-
- -
-
-

And lastly, this one. Checkmate.

-

Donec ullamcorper nulla non metus auctor fringilla. Vestibulum id ligula porta felis euismod - semper. Praesent commodo cursus magna, vel scelerisque nisl consectetur. Fusce dapibus, tellus ac cursus - commodo.

-
-
- -
-
- - - -
- -
-
-

Contact

-
-
-
- -
-
- -
-
-
-
-
- -
- -
-
-
- -
-
- - -
-
- - -
- - Send -
-
-
- -
- -
- - Back to top -
- Β© 2017-2020 Company, Inc. Β· - Privacy Β· - Terms -
-
- - - - - - - -
- - - \ No newline at end of file diff --git a/examples/site-rebrand-tutorial/FastPage/js/scroll.js b/examples/site-rebrand-tutorial/FastPage/js/scroll.js deleted file mode 100644 index 84a46cbdf5c..00000000000 --- a/examples/site-rebrand-tutorial/FastPage/js/scroll.js +++ /dev/null @@ -1,20 +0,0 @@ -const anchors = Array.from(document.querySelectorAll('a[name]')); -const xPositions = anchors.map(a => { return a.getBoundingClientRect().top + window.pageYOffset;} ); -const navItems = Array.from(document.querySelectorAll('li.nav-item')); - -document.addEventListener('scroll', e => { - const maxScroll = window.pageYOffset + window.innerHeight + 100 > document.body.scrollHeight; - - if (maxScroll) { - navItems.forEach(n => {n.classList.remove('active');}); - navItems[anchors.length - 1].classList.add('active'); - } else { - for(let i = anchors.length - 1; i >= 0; --i) { - if (window.pageYOffset + 120 > xPositions[i]) { - navItems.forEach(n => {n.classList.remove('active');}); - navItems[i].classList.add('active'); - return; - } - } - } -}); diff --git a/examples/site-rebrand-tutorial/design-panel.png b/examples/site-rebrand-tutorial/design-panel.png deleted file mode 100644 index d4a9faf0479..00000000000 Binary files a/examples/site-rebrand-tutorial/design-panel.png and /dev/null differ diff --git a/examples/site-rebrand-tutorial/example-controls.png b/examples/site-rebrand-tutorial/example-controls.png deleted file mode 100644 index 50c63ed5f6b..00000000000 Binary files a/examples/site-rebrand-tutorial/example-controls.png and /dev/null differ diff --git a/examples/site-rebrand-tutorial/intro-video.mp4 b/examples/site-rebrand-tutorial/intro-video.mp4 deleted file mode 100644 index 9c7a055cda1..00000000000 Binary files a/examples/site-rebrand-tutorial/intro-video.mp4 and /dev/null differ diff --git a/examples/site-rebrand-tutorial/side-by-side.png b/examples/site-rebrand-tutorial/side-by-side.png deleted file mode 100644 index cc8f58a418a..00000000000 Binary files a/examples/site-rebrand-tutorial/side-by-side.png and /dev/null differ diff --git a/examples/site-rebrand-tutorial/site-structure.png b/examples/site-rebrand-tutorial/site-structure.png deleted file mode 100644 index f69c5bde99f..00000000000 Binary files a/examples/site-rebrand-tutorial/site-structure.png and /dev/null differ diff --git a/examples/site-rebrand-tutorial/walk-through.md b/examples/site-rebrand-tutorial/walk-through.md deleted file mode 100644 index f8d300af0a0..00000000000 --- a/examples/site-rebrand-tutorial/walk-through.md +++ /dev/null @@ -1,562 +0,0 @@ - - -# Walkthrough of FAST web components - -If you've ever tried to build consistent custom markup structures for a website or an app, you might have looked at web components. As they're standards compliant and supported by all the main evergreen browsers, web components allow you to define reusable and encapsulated HTML tags. - -FAST gives you a collection of packages that include web components to define a set of reusable, stylable, and flexible HTML components. These components can encapsulate an entire user experience design language like Microsoft's Fluent design or Google's Material design. The other packages include an intelligent color system and a design system provider. - -This walkthrough will introduce you to FAST web components. You'll add the components to an existing website and see the impact of changing the design systems' properties. You'll see how to completely alter the design language of a website, by only changing a single line of code. - -## Prerequisites - -In this walkthrough, you'll be editing an existing HTML static website. If you'd like to follow the step-by-step, guide you'll need some tools. Start with a code editor like [Visual Studio Code](https://code.visualstudio.com/). You'll also need a local development server. A simple way to set one up is to use the [Live Server](https://marketplace.visualstudio.com/items?itemName=ritwickdey.LiveServer) extension for VS Code. The example code used in this walkthrough is stored on GitHub so you'll need a way to clone the repository, either by installing Git or using the built-in VS Code Git tooling. - -You should have some understanding of web design and experience of HTML, CSS, and JavaScript. Experience of web components is not required. - -## Scenario - -Imagine you work for a company that has an existing website. Your company's design department has been asked to re-brand the company and need to apply this new look and feel to the website. The current website has been built with classic HTML and CSS for styling. You'd like to take this opportunity to implement web components and have recently discovered FAST as an option. - -## The website - -![A screenshot of the starter website](website.png) - -To start this walkthrough, you'll clone your company's existing website. Exploring the code you'll see it's a simple static website with this folder structure: - -![Diagram showing the site structure with folders for CSS, images, JavaScript, and an index.html file](site-structure.png) - -The web page itself is simple and has a menu, hero, gallery, contact, and footer sections. - -```html - -
- -
- -
- -
- -