├── .gitignore
├── .vscode
└── launch.json
├── README.md
├── SECURITY.md
├── build.yml
├── dist
├── 9p1j8s7ccwwt_us_en-us.html
├── badge
│ └── ms-store-badge.bundled.js
├── iframe.html
├── images
│ ├── af dark.svg
│ ├── af light.svg
│ ├── am dark.svg
│ ├── am light.svg
│ ├── ar dark.svg
│ ├── ar light.svg
│ ├── as dark.svg
│ ├── as light.svg
│ ├── az dark.svg
│ ├── az light.svg
│ ├── bg dark.svg
│ ├── bg light.svg
│ ├── bn dark.svg
│ ├── bn light.svg
│ ├── bs dark.svg
│ ├── bs light.svg
│ ├── ca dark.svg
│ ├── ca light.svg
│ ├── cs dark.svg
│ ├── cs light.svg
│ ├── cy dark.svg
│ ├── cy light.svg
│ ├── da dark.svg
│ ├── da light.svg
│ ├── de dark.svg
│ ├── de light.svg
│ ├── el dark.svg
│ ├── el light.svg
│ ├── en-us dark.svg
│ ├── en-us light.svg
│ ├── es dark.svg
│ ├── es light.svg
│ ├── et dark.svg
│ ├── et light.svg
│ ├── fa dark.svg
│ ├── fa light.svg
│ ├── fi dark.svg
│ ├── fi light.svg
│ ├── fil dark.svg
│ ├── fil light.svg
│ ├── fr dark.svg
│ ├── fr light.svg
│ ├── ga dark.svg
│ ├── ga light.svg
│ ├── gd dark.svg
│ ├── gd light.svg
│ ├── gl dark.svg
│ ├── gl light.svg
│ ├── gu dark.svg
│ ├── gu light.svg
│ ├── he dark.svg
│ ├── he light.svg
│ ├── hi dark.svg
│ ├── hi light.svg
│ ├── hr dark.svg
│ ├── hr light.svg
│ ├── hu dark.svg
│ ├── hu light.svg
│ ├── hy dark.svg
│ ├── hy light.svg
│ ├── id dark.svg
│ ├── id light.svg
│ ├── is dark.svg
│ ├── is light.svg
│ ├── it dark.svg
│ ├── it light.svg
│ ├── ja dark.svg
│ ├── ja light.svg
│ ├── ka dark.svg
│ ├── ka light.svg
│ ├── kk dark.svg
│ ├── kk light.svg
│ ├── km dark.svg
│ ├── km light.svg
│ ├── kn dark.svg
│ ├── kn light.svg
│ ├── ko dark.svg
│ ├── ko light.svg
│ ├── kok dark.svg
│ ├── kok light.svg
│ ├── lb dark.svg
│ ├── lb light.svg
│ ├── lo dark.svg
│ ├── lo light.svg
│ ├── lt dark.svg
│ ├── lt light.svg
│ ├── lv dark.svg
│ ├── lv light.svg
│ ├── mi dark.svg
│ ├── mi light.svg
│ ├── mk dark.svg
│ ├── mk light.svg
│ ├── ml dark.svg
│ ├── ml light.svg
│ ├── mr dark.svg
│ ├── mr light.svg
│ ├── ms dark.svg
│ ├── ms light.svg
│ ├── mt dark.svg
│ ├── mt light.svg
│ ├── ne dark.svg
│ ├── ne light.svg
│ ├── nl dark.svg
│ ├── nl light.svg
│ ├── nn dark.svg
│ ├── nn light.svg
│ ├── or dark.svg
│ ├── or light.svg
│ ├── pa dark.svg
│ ├── pa light.svg
│ ├── pl dark.svg
│ ├── pl light.svg
│ ├── pt-br dark.svg
│ ├── pt-br light.svg
│ ├── pt-pt dark.svg
│ ├── pt-pt light.svg
│ ├── quz dark.svg
│ ├── quz light.svg
│ ├── ro dark.svg
│ ├── ro light.svg
│ ├── ru dark.svg
│ ├── ru light.svg
│ ├── sk dark.svg
│ ├── sk light.svg
│ ├── sl dark.svg
│ ├── sl light.svg
│ ├── sq dark.svg
│ ├── sq light.svg
│ ├── sr dark.svg
│ ├── sr light.svg
│ ├── sv dark.svg
│ ├── sv light.svg
│ ├── ta dark.svg
│ ├── ta light.svg
│ ├── te dark.svg
│ ├── te light.svg
│ ├── th dark.svg
│ ├── th light.svg
│ ├── tr dark.svg
│ ├── tr light.svg
│ ├── ug dark.svg
│ ├── ug light.svg
│ ├── uk dark.svg
│ ├── uk light.svg
│ ├── ur dark.svg
│ ├── ur light.svg
│ ├── uz dark.svg
│ ├── uz light.svg
│ ├── vi dark.svg
│ ├── vi light.svg
│ ├── zh-cn dark.svg
│ ├── zh-cn light.svg
│ ├── zh-tw dark.svg
│ └── zh-tw light.svg
├── index.html
├── ms-store-badge.bundled.js
└── staticwebapp.config.json
├── images
└── discord-psi.png
├── package-lock.json
├── package.json
├── release.yml
├── rollup.config.js
├── src
├── 9p1j8s7ccwwt_us_en-us.html
├── iframe.html
├── images
│ ├── af dark.svg
│ ├── af light.svg
│ ├── am dark.svg
│ ├── am light.svg
│ ├── ar dark.svg
│ ├── ar light.svg
│ ├── as dark.svg
│ ├── as light.svg
│ ├── az dark.svg
│ ├── az light.svg
│ ├── bg dark.svg
│ ├── bg light.svg
│ ├── bn dark.svg
│ ├── bn light.svg
│ ├── bs dark.svg
│ ├── bs light.svg
│ ├── ca dark.svg
│ ├── ca light.svg
│ ├── cs dark.svg
│ ├── cs light.svg
│ ├── cy dark.svg
│ ├── cy light.svg
│ ├── da dark.svg
│ ├── da light.svg
│ ├── de dark.svg
│ ├── de light.svg
│ ├── el dark.svg
│ ├── el light.svg
│ ├── en-us dark.svg
│ ├── en-us light.svg
│ ├── es dark.svg
│ ├── es light.svg
│ ├── et dark.svg
│ ├── et light.svg
│ ├── fa dark.svg
│ ├── fa light.svg
│ ├── fi dark.svg
│ ├── fi light.svg
│ ├── fil dark.svg
│ ├── fil light.svg
│ ├── fr dark.svg
│ ├── fr light.svg
│ ├── ga dark.svg
│ ├── ga light.svg
│ ├── gd dark.svg
│ ├── gd light.svg
│ ├── gl dark.svg
│ ├── gl light.svg
│ ├── gu dark.svg
│ ├── gu light.svg
│ ├── he dark.svg
│ ├── he light.svg
│ ├── hi dark.svg
│ ├── hi light.svg
│ ├── hr dark.svg
│ ├── hr light.svg
│ ├── hu dark.svg
│ ├── hu light.svg
│ ├── hy dark.svg
│ ├── hy light.svg
│ ├── id dark.svg
│ ├── id light.svg
│ ├── is dark.svg
│ ├── is light.svg
│ ├── it dark.svg
│ ├── it light.svg
│ ├── ja dark.svg
│ ├── ja light.svg
│ ├── ka dark.svg
│ ├── ka light.svg
│ ├── kk dark.svg
│ ├── kk light.svg
│ ├── km dark.svg
│ ├── km light.svg
│ ├── kn dark.svg
│ ├── kn light.svg
│ ├── ko dark.svg
│ ├── ko light.svg
│ ├── kok dark.svg
│ ├── kok light.svg
│ ├── lb dark.svg
│ ├── lb light.svg
│ ├── lo dark.svg
│ ├── lo light.svg
│ ├── lt dark.svg
│ ├── lt light.svg
│ ├── lv dark.svg
│ ├── lv light.svg
│ ├── mi dark.svg
│ ├── mi light.svg
│ ├── mk dark.svg
│ ├── mk light.svg
│ ├── ml dark.svg
│ ├── ml light.svg
│ ├── mr dark.svg
│ ├── mr light.svg
│ ├── ms dark.svg
│ ├── ms light.svg
│ ├── mt dark.svg
│ ├── mt light.svg
│ ├── ne dark.svg
│ ├── ne light.svg
│ ├── nl dark.svg
│ ├── nl light.svg
│ ├── nn dark.svg
│ ├── nn light.svg
│ ├── or dark.svg
│ ├── or light.svg
│ ├── pa dark.svg
│ ├── pa light.svg
│ ├── pl dark.svg
│ ├── pl light.svg
│ ├── pt-br dark.svg
│ ├── pt-br light.svg
│ ├── pt-pt dark.svg
│ ├── pt-pt light.svg
│ ├── quz dark.svg
│ ├── quz light.svg
│ ├── ro dark.svg
│ ├── ro light.svg
│ ├── ru dark.svg
│ ├── ru light.svg
│ ├── sk dark.svg
│ ├── sk light.svg
│ ├── sl dark.svg
│ ├── sl light.svg
│ ├── sq dark.svg
│ ├── sq light.svg
│ ├── sr dark.svg
│ ├── sr light.svg
│ ├── sv dark.svg
│ ├── sv light.svg
│ ├── ta dark.svg
│ ├── ta light.svg
│ ├── te dark.svg
│ ├── te light.svg
│ ├── th dark.svg
│ ├── th light.svg
│ ├── tr dark.svg
│ ├── tr light.svg
│ ├── ug dark.svg
│ ├── ug light.svg
│ ├── uk dark.svg
│ ├── uk light.svg
│ ├── ur dark.svg
│ ├── ur light.svg
│ ├── uz dark.svg
│ ├── uz light.svg
│ ├── vi dark.svg
│ ├── vi light.svg
│ ├── zh-cn dark.svg
│ ├── zh-cn light.svg
│ ├── zh-tw dark.svg
│ └── zh-tw light.svg
├── index.html
├── ms-store-badge.d.ts
├── ms-store-badge.ts
├── psi-service.d.ts
├── psi-service.d.ts.map
├── psi-service.js
├── psi-service.js.map
├── psi-service.ts
├── staticwebapp.config.json
├── throttle-async.d.ts
├── throttle-async.d.ts.map
├── throttle-async.js
├── throttle-async.js.map
└── throttle-async.ts
├── tsconfig.json
└── web-dev-server.config.mjs
/.gitignore:
--------------------------------------------------------------------------------
1 | node_modules/
2 | /lib/
3 | /test/
4 | custom-elements.json
5 | # top level source
6 | my-element.js
7 | my-element.js.map
8 | my-element.d.ts
9 | my-element.d.ts.map
10 | ms-store-badge.d.ts.map
11 | ms-store-badge.js
12 | ms-store-badge.js.map
13 |
--------------------------------------------------------------------------------
/.vscode/launch.json:
--------------------------------------------------------------------------------
1 | {
2 | // Use IntelliSense to learn about possible attributes.
3 | // Hover to view descriptions of existing attributes.
4 | // For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387
5 | "version": "0.2.0",
6 | "configurations": [
7 | {
8 | "type": "pwa-chrome",
9 | "request": "launch",
10 | "name": "Launch Chrome against localhost",
11 | "url": "http://localhost:8000",
12 | "webRoot": "${workspaceFolder}/src"
13 | }
14 | ]
15 | }
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # App Store Badge
2 |
3 | This repository contains the source code for web component that displays the "Get this app on the Microsoft Store" badge.
4 |
5 | ## Usage
6 |
7 | Generate your own app badge using https://apps.microsoft.com/store/app-badge/
8 |
9 | Alternately, add the following code in your HTML where you want the button to appear:
10 |
11 | ```html
12 |
13 |
14 | ```
15 |
16 | The component has some additional configuration options:
17 |
18 | | Option | Type | Default value | Description |
19 | |--------------|-----------|------------|------------|
20 | | productid | string | undefined | Your app ID in the Microsoft Store. You can find this value by navigating to your app in the [Microsoft Store for Web](https://apps.microsoft.com) and grabbing the last part of the URL. The Discord app, for example, is at [https://apps.microsoft.com/store/detail/discord/XPDC2RH70K22MN](https://apps.microsoft.com/store/detail/discord/XPDC2RH70K22MN), so its product ID is `XPDC2RH70K22MN` |
21 | | productname | string | undefined | Your app product name in the Microsoft Store. This is only used for the default direct method of installation, where your product name will be part of the installer template.
22 | | cid | string | undefined | Your app campaign code for analytics purposes. If the user clicks the app badge, this value will be passed to analytics and will be available to you in your [Microsoft Partner Center](https://partner.microsoft.com/en-us/dashboard/home) reports. |
23 | | window-mode | "direct" or "full" | "direct" | Configure the badge to automatically download your app with direct mode, or open your app in full store mode.
In `direct` mode, users who click your app badge will see the default portable store installer, an executable that allows users to download your product directly from the browser.  In `full` mode, users who click your app badge will see full store app: ) |
24 | | theme | "dark" or "light" or "auto" | "dark" | Configure the badge theme dark mode, light mode, or auto mode. Auto mode detects the user's dark mode preference and sets the badge theme accordingly.
`dark` should be used on sites with light backgrounds:
`light` should be use on sites with dark backgrounds: |
25 | | animation | "on" or "off" | "off" | When `on`, the badge will use an animation and shadow on hover. Alternately, you may build and apply your own animations by adding CSS to the `img` part. See [styling the badge](#styling-the-badge) for more information. |
26 | | language | string | '' | The language to display the app badge. If left empty, the language will be detected from the user's browser `navigator.userAgent.language`. Sample of specifying a different language:
See supported languages
Afrikaans: "af"
Arabic: "ar"
Belarusian: "be"
Bulgarian: "bg"
Bengali: "bn"
Bosnian: "bs"
Catalan: "ca"
Chinese (Simplified): "zh-cn"
Chinese (Traditional): "zh-tw"
Czech: "cs"
Danish: "da"
Dutch: "nl"
German: "de"
Greek: "el"
English: "en"
Spanish: "es"
Estonian: "et"
Persian: "fa"
Finnish: "fi"
Filipino: "fil"
French: "fr"
Galician: "gl"
Hebrew: "he"
Hindi: "hi"
Croatian: "hr"
Hungarian: "hu"
Indonesian: "id"
Icelandic: "is"
Italian: "it"
Japanese: "ja"
Georgian: "ka"
Kazakh: "kk"
Korean: "ko"
Lithuanian: "lt"
Latvian: "lv"
Malay: "ms"
Norwegian: "nb"
Polish: "pl"
Portuguese (Brazil): "pt-br"
Portuguese (Portugal): "pt-pt"
Romanian: "ro"
Russian: "ru"
Slovak: "sk"
Slovenian: "sl"
Serbian: "sr"
Swedish: "sv"
Swahili: "sw"
Thai: "th"
Turkish: "tr"
Ukrainian: "uk"
Vietnamese: "vi"
Welsh: "cy"
|
27 |
28 | Example using all the available options:
29 |
30 | ```html
31 |
32 |
33 | ```
34 |
35 | ## Styling the badge
36 |
37 | To style the app badge web component, use [CSS parts](https://developer.mozilla.org/en-US/docs/Web/CSS/::part) to style the badge image. Specifically, the app badge web component exposes the badge image as `img` part:
38 |
39 | ```css
40 | /* Customize the badge's appearance */
41 | ms-store-badge::part(img) {
42 | max-height: 52px;
43 | }
44 | ```
45 |
46 | ## Why a web component?
47 |
48 | Most app store badges are a simple image with a link to the web store. Why is this a web component?
49 |
50 | In short, for better localization and better user experience.
51 |
52 | - **Localization**: the web component supports automatic detection of the user's locale, showing a localized button to the user based on the user's browser locale.
53 | - **Fewer security prompts**: if the user is on Edge on Windows, no browser security prompt ("this site is trying to launch Microsoft Store") is shown.
54 | - **Better behavior on other OSes**: If the user is on MacOS or other non-Windows OS and they click your app badge, instead of trying (and failing) to launch the Microsoft Store app, it instead launches the OS's native share dialog, allowing the user to share the link to your app.
55 | - **Automatic theme support**: You can configure your app badge to use automatic theme detection. When `theme="auto"`, the app badge will be themed based on whether the user has [dark mode](https://css-tricks.com/dark-modes-with-css/) enabled.
56 |
57 | ## HTML-only
58 |
59 | While the app badge script is small (about 9k), there are contexts where a script doesn't make sense: Github markdown pages, static sites, or other contexts without Javascript available. For such contexts, you can use a simple image with link:
60 |
61 | ```html
62 |
63 |
64 |
65 |
66 | ```
67 |
68 | Be mindful that the HTML-only version of the badge loses some functionality of the full badge. For example, automatic theme detection, OS-specific behavior (e.g. launch the Store on Windows, or open the [apps's web Product Description Page](https://apps.microsoft.com/store/detail/chavah-messianic-radio/9NHKJB6LPPTV) on non-Windows OS), localization, and fewer user prompts for Edge users are not available in the HTML-only version of the badge.
69 |
70 | ## Running the code
71 |
72 | To run code locally, `npm run dev`, then launch http://localhost:8000/create-your-own.html
73 |
74 | To build for production, `npm run build`. This will create the production artifacts in `/dist`.
75 |
76 | ## Deploying
77 |
78 | ADO release pipeline is set to deploy successful builds of main to the app badge CDN. Code changes are then synced to GH repo for open source visibility.
79 |
--------------------------------------------------------------------------------
/SECURITY.md:
--------------------------------------------------------------------------------
1 |
2 |
3 | ## Security
4 |
5 | Microsoft takes the security of our software products and services seriously, which includes all source code repositories managed through our GitHub organizations, which include [Microsoft](https://github.com/microsoft), [Azure](https://github.com/Azure), [DotNet](https://github.com/dotnet), [AspNet](https://github.com/aspnet), [Xamarin](https://github.com/xamarin), and [our GitHub organizations](https://opensource.microsoft.com/).
6 |
7 | If you believe you have found a security vulnerability in any Microsoft-owned repository that meets [Microsoft's definition of a security vulnerability](https://aka.ms/opensource/security/definition), please report it to us as described below.
8 |
9 | ## Reporting Security Issues
10 |
11 | **Please do not report security vulnerabilities through public GitHub issues.**
12 |
13 | Instead, please report them to the Microsoft Security Response Center (MSRC) at [https://msrc.microsoft.com/create-report](https://aka.ms/opensource/security/create-report).
14 |
15 | 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 [Microsoft Security Response Center PGP Key page](https://aka.ms/opensource/security/pgpkey).
16 |
17 | 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://aka.ms/opensource/security/msrc).
18 |
19 | Please include the requested information listed below (as much as you can provide) to help us better understand the nature and scope of the possible issue:
20 |
21 | * Type of issue (e.g. buffer overflow, SQL injection, cross-site scripting, etc.)
22 | * Full paths of source file(s) related to the manifestation of the issue
23 | * The location of the affected source code (tag/branch/commit or direct URL)
24 | * Any special configuration required to reproduce the issue
25 | * Step-by-step instructions to reproduce the issue
26 | * Proof-of-concept or exploit code (if possible)
27 | * Impact of the issue, including how an attacker might exploit the issue
28 |
29 | This information will help us triage your report more quickly.
30 |
31 | If you are reporting for a bug bounty, more complete reports can contribute to a higher bounty award. Please visit our [Microsoft Bug Bounty Program](https://aka.ms/opensource/security/bounty) page for more details about our active programs.
32 |
33 | ## Preferred Languages
34 |
35 | We prefer all communications to be in English.
36 |
37 | ## Policy
38 |
39 | Microsoft follows the principle of [Coordinated Vulnerability Disclosure](https://aka.ms/opensource/security/cvd).
40 |
41 |
42 |
--------------------------------------------------------------------------------
/build.yml:
--------------------------------------------------------------------------------
1 | # This Yaml Document has been converted by ESAI Yaml Pipeline Conversion Tool.
2 |
3 | trigger:
4 | - main
5 | resources:
6 | repositories:
7 | - repository: 1ESPipelineTemplates
8 | type: git
9 | name: 1ESPipelineTemplates/1ESPipelineTemplates
10 | ref: refs/tags/release
11 | extends:
12 | template: v1/1ES.Official.PipelineTemplate.yml@1ESPipelineTemplates
13 | parameters:
14 | pool:
15 | name: StoreWebBuildPool-Centeral
16 | customBuildTags:
17 | - ES365AIMigrationTooling
18 | stages:
19 | - stage: stage
20 | jobs:
21 | - job: job
22 | templateContext:
23 | outputs:
24 | - output: pipelineArtifact
25 | displayName: 'Publish build artifact'
26 | targetPath: '$(System.DefaultWorkingDirectory)/dist'
27 | artifactName: 'ms-store-badge-artifacts'
28 | publishLocation: 'Container'
29 | steps:
30 | - checkout: self
31 | submodules: true
32 |
33 | - script: |
34 | icacls "$(Build.SourcesDirectory)" /grant Everyone:F /T
35 | if exist "$(Build.SourcesDirectory)\.npmrc" (
36 | dir "$(Build.SourcesDirectory)\.npmrc"
37 | ) else (
38 | echo .npmrc file not found
39 | echo. > "$(Build.SourcesDirectory)\.npmrc"
40 | )
41 | displayName: 'Add vsts directory permissions'
42 |
43 | - script: |
44 | npm install -g typescript
45 | displayName: 'Install TypeScript'
46 |
47 | - task: NpmAuthenticate@0
48 | inputs:
49 | workingFile: '.npmrc'
50 | displayName: 'Authenticate to NPM'
51 |
52 | - script: |
53 | echo "Cleaning dist directory"
54 | rm -rf "$(System.DefaultWorkingDirectory)/dist"
55 | displayName: 'Clean dist directory'
56 |
57 | - script: |
58 | npm install
59 | displayName: 'Install dependencies'
60 |
61 | - script: |
62 | echo "Listing current directory contents:"
63 | dir
64 | displayName: 'List directory contents after install'
65 |
66 | - script: |
67 | cd src
68 | tsc -t es2015 --moduleResolution node ms-store-badge.ts
69 | displayName: 'Compile TypeScript'
70 |
71 | - script: |
72 | npm run build:prod
73 | displayName: 'Build badge'
74 |
75 | - script: |
76 | echo "Listing dist directory structure:"
77 | dir dist /s
78 | displayName: 'List dist directory structure'
79 |
80 | - script: |
81 | echo "Listing current directory contents:"
82 | dir
83 | displayName: 'List current directory contents after build'
84 |
85 | - script: |
86 | echo "Setting up GitHub repository"
87 | git config --global user.name "Justin Lau"
88 | git config --global user.email "justinlau@microsoft.com"
89 | git remote add github https://$(GITHUB_TOKEN)@github.com/microsoft/app-store-badge.git
90 | git fetch github
91 | git checkout github/main
92 | git merge origin/main -X ours --allow-unrelated-histories --no-edit
93 | git rm .npmrc -f
94 | git add -A
95 | git commit -m "Sync from ADO repo" || echo "No changes to commit"
96 | git push github HEAD:main --force
97 | displayName: 'Sync ADO Repo to GitHub'
98 | env:
99 | GITHUB_TOKEN: $(GITHUB_TOKEN)
--------------------------------------------------------------------------------
/dist/badge/ms-store-badge.bundled.js:
--------------------------------------------------------------------------------
1 | var t=function(t,i,e,n){return new(e||(e=Promise))((function(o,r){function s(t){try{c(n.next(t))}catch(t){r(t)}}function a(t){try{c(n.throw(t))}catch(t){r(t)}}function c(t){var i;t.done?o(t.value):(i=t.value,i instanceof e?i:new e((function(t){t(i)}))).then(s,a)}c((n=n.apply(t,i||[])).next())}))};function i(i,e){return t(this,arguments,void 0,(function*(i,e,n={},o){const r="psi_f_svc",s={method:"GET",headers:{Origin:"https://apps.microsoft.com",Referer:document.URL,"Access-Control-Request-Method":"GET","X-Correlation-Id":crypto.randomUUID(),"Content-Type":"application/octet-stream"},cache:"no-cache",params:new URLSearchParams(o)},a=Object.assign(Object.assign({},s),n);let c=null;try{c=yield fetch(`${o}`,a)}catch(t){window.location.href=`ms-windows-store://pdp/?productid=${i}&ocid=${r}na`}(null==c?void 0:c.ok)?function(i){t(this,void 0,void 0,(function*(){var t;const n=null!==(t=i.headers.get("X-PSI-FileName"))&&void 0!==t?t:`${e} Installer.exe`,o=yield i.blob(),r=URL.createObjectURL(o),s=document.createElement("a");s.href=r,s.download=decodeURIComponent(n),s.style.display="none",document.body.appendChild(s);try{s.click(),yield new Promise((t=>setTimeout(t,1e3)))}catch(t){}finally{URL.revokeObjectURL(r),document.body.removeChild(s)}}))}(c):function(e){t(this,void 0,void 0,(function*(){const t=null==e?void 0:e.status;window.location.href=`ms-windows-store://pdp/?productid=${i}&ocid=${r}${t}`}))}(c)}))}var e=function(t,i,e,n){return new(e||(e=Promise))((function(o,r){function s(t){try{c(n.next(t))}catch(t){r(t)}}function a(t){try{c(n.throw(t))}catch(t){r(t)}}function c(t){var i;t.done?o(t.value):(i=t.value,i instanceof e?i:new e((function(t){t(i)}))).then(s,a)}c((n=n.apply(t,i||[])).next())}))};let n=!1;var o,r,s,a,c,h,d,l,u,f=function(t,i,e,n){return new(e||(e=Promise))((function(o,r){function s(t){try{c(n.next(t))}catch(t){r(t)}}function a(t){try{c(n.throw(t))}catch(t){r(t)}}function c(t){var i;t.done?o(t.value):(i=t.value,i instanceof e?i:new e((function(t){t(i)}))).then(s,a)}c((n=n.apply(t,i||[])).next())}))},m=function(t,i,e,n,o){if("m"===n)throw new TypeError("Private method is not writable");if("a"===n&&!o)throw new TypeError("Private accessor was defined without a setter");if("function"==typeof i?t!==i||!o:!i.has(t))throw new TypeError("Cannot write private member to an object whose class did not declare it");return"a"===n?o.call(t,e):o?o.value=e:i.set(t,e),e},p=function(t,i,e,n){if("a"===e&&!n)throw new TypeError("Private accessor was defined without a getter");if("function"==typeof i?t!==i||!n:!i.has(t))throw new TypeError("Cannot read private member from an object whose class did not declare it");return"m"===e?n:"a"===e?n.call(t):n?n.value:i.get(t)};class g extends HTMLElement{constructor(){super(),o.add(this),this.productId="",this.productName="",this.cid="",this.size="large",this.windowMode="direct",this.theme="dark",this.language="",this.animation="off",s.set(this,r.englishLanguage),a.set(this,"prod"),c.set(this,"dev"===p(this,a,"f")?"iframe.html":"https://get.microsoft.com/iframe.html"),h.set(this,"dev"===p(this,a,"f")?"/images":"https://get.microsoft.com/images"),d.set(this,{isWindows:!1,windowsVersion:null,isEdgeBrowser:!1}),l.set(this,!1),this.PSIDownloadUrl="https://get.microsoft.com/installer/download/",this.throttleDownload=function(t,i){return(...o)=>e(this,void 0,void 0,(function*(){if(!n){n=!0;try{yield t(...o)}finally{setTimeout((()=>n=!1),i)}}}))}(i,1500),this.imgPSIHandler=()=>this.throttleDownload(this.productId,this.productName||"Microsoft Store Direct",void 0,this.getPSIUrl()),this.imgPDPHandler=t=>this.launchApp(t),this.getPlatformDetails().then((t=>m(this,d,t,"f"))),m(this,s,r.getSupportedLanguageFromCode(this.language),"f"),this.language=p(this,s,"f").code;const t=this.attachShadow({mode:"open"}),u=this.createStyle(),f=this.createHtml();t.appendChild(u),t.appendChild(f)}updateImageSrc(){var t;const i=null===(t=this.shadowRoot)||void 0===t?void 0:t.querySelector("img");i&&(i.setAttribute("src",this.getImageSource()),i.className=this.getImageClass())}updateListeners(){var t;const i=null===(t=this.shadowRoot)||void 0===t?void 0:t.querySelector("img");null==i||i.removeEventListener("click",this.imgPDPHandler),null==i||i.removeEventListener("click",this.imgPSIHandler),"direct"===this.windowMode?null==i||i.addEventListener("click",this.imgPSIHandler):null==i||i.addEventListener("click",this.imgPDPHandler)}connectedCallback(){}static get observedAttributes(){return["productid","productname","cid","window-mode","theme","size","language","animation"]}attributeChangedCallback(t,i,e){var n;"size"!==t||"large"!==e&&"small"!==e||i===e?"language"!==t||e===i||"string"!=typeof e&&e?"productid"===t&&e!==i&&"string"==typeof e?this.productId=e:"productname"===t&&e!==i&&"string"==typeof e?this.productName=e:"cid"===t&&e!==i&&"string"==typeof e?this.cid=e:"window-mode"!==t||"popup"!==e&&"full"!==e&&"direct"!==e||i===e?"theme"!==t||"dark"!=e&&"light"!==e&&"auto"!==e||i===e?"animation"!==t||"on"!==e&&"off"!==e||i===e||(this.animation=e,null===(n=this.shadowRoot)||void 0===n||n.appendChild(this.createStyle())):(this.theme=e,this.updateImageSrc()):("popup"===this.windowMode&&(this.windowMode="full"),this.windowMode=e,this.updateImageSrc(),this.updateListeners()):(m(this,s,r.getSupportedLanguageFromCode(e),"f"),this.language=p(this,s,"f").code,this.updateImageSrc()):(this.size=e,this.updateImageSrc())}createStyle(){var t="";t="on"===this.animation?"\n :host {\n display: inline-block;\n cursor: pointer;\n height: fit-content;\n }\n\n iframe {\n border: none;\n width: 0px;\n height: 0px;\n }\n\n img {\n border-radius: 8px;\n transition: 0.35s ease;\n }\n \n img:hover {\n transform: translate(0, -4px);\n cursor: pointer;\n box-shadow: 0 12px 40px 20px rgba(0, 0, 0, 0.05);\n }\n \n img.large {\n height: 104px;\n }\n \n div {\n height: 104px;\n }":"\n :host {\n display: inline-block;\n cursor: pointer;\n height: fit-content;\n }\n\n iframe {\n border: none;\n width: 0px;\n height: 0px;\n }\n\n img {\n width: auto;\n border-radius: 8px;\n }\n\n img.large {\n height: 104px;\n }\n \n div {\n height: 104px;\n }";const i=document.createElement("style");return i.textContent=t,i}createHtml(){const t=document.createElement("div");return t.appendChild(this.createImage()),t.appendChild(this.createIFrame()),t}getPlatformDetails(){return f(this,void 0,void 0,(function*(){const t=navigator;if(t.userAgentData&&t.userAgentData.getHighEntropyValues)try{const i=yield t.userAgentData.getHighEntropyValues(["platform","platformVersion"]),e="Windows"===i.platform;return{isWindows:e,windowsVersion:e?parseFloat((null==i?void 0:i.platformVersion)||""):null,isEdgeBrowser:(t.userAgentData.brands||[]).some((t=>"Microsoft Edge"===t.brand))}}catch(t){}const i=new RegExp(/.?Windows NT (\d+\.?\d?\.?\d?\.?\d?)/gi).exec(navigator.userAgent);return i&&i.length>=2?{isWindows:!0,windowsVersion:parseFloat(i[1]),isEdgeBrowser:!!navigator.userAgent.match("Edg/")}:{isWindows:!1,windowsVersion:null,isEdgeBrowser:!!navigator.userAgent.match("Edg/")}}))}static getSupportedLanguageFromCode(t){if(!t)return r.getSupportedLanguageFromUserAgent();const i=r.supportedLanguages.find((i=>i.code===t.toLowerCase()))||r.supportedLanguages.find((i=>i.code.substring(0,3)===t.toLowerCase()))||r.supportedLanguages.find((i=>i.code.substring(0,2)===t.toLowerCase()));return i||r.englishLanguage}static getSupportedLanguageFromUserAgent(){const t=r.supportedLanguages.find((t=>t.code.toLowerCase()===(navigator.language||"").toLowerCase()));if(t)return t;if(navigator.languages){var i=navigator.languages.map((t=>r.supportedLanguages.find((i=>i.code===t)))).find((t=>!!t));if(i)return i}const e=navigator.language.indexOf("-");if(e>0){const t=navigator.language.substring(0,e),i=r.supportedLanguages.find((i=>i.code.toLowerCase()===t.toLowerCase()));if(i)return i}return r.englishLanguage}createIFrame(){const t=document.createElement("iframe");return t.setAttribute("loading","eager"),t.title="Microsoft Store App Badge",t.src=p(this,c,"f"),t}createImage(){const t=document.createElement("img");return t.setAttribute("part","img"),t.src=this.getImageSource(),t.className=this.getImageClass(),t.alt="Microsoft Store app badge","direct"===this.windowMode?t.addEventListener("click",this.imgPSIHandler):t.addEventListener("click",this.imgPDPHandler),t}getImageSource(){var t=null;if("dark"===this.theme)t=p(this,s,"f").imageLarge.fileName;else if("light"===this.theme)t=p(this,s,"f").imageLargeLight.fileName;else if("auto"===this.theme){t=window.matchMedia("(prefers-color-scheme:dark)").matches?p(this,s,"f").imageLargeLight.fileName:p(this,s,"f").imageLarge.fileName}return`${p(this,h,"f")}/${t}`}getImageClass(){return"large"===this.size?"large":"small"}launchApp(t){this.productId&&(p(this,d,"f").isWindows&&p(this,d,"f").isEdgeBrowser?this.launchStoreAppPdpViaWhitelistedDomain():p(this,d,"f").isWindows?this.launchFullStoreApp():this.launchStoreWebPdp(t))}getPSIUrl(){return`${this.PSIDownloadUrl}${this.productId.toUpperCase()}?referrer=appbadge&source=${encodeURIComponent(window.location.hostname.toLowerCase())}`}launchFullStoreApp(){const t=new URLSearchParams;t.append("productid",this.productId),t.append("referrer","appbadge"),t.append("source",window.location.hostname.toLowerCase()),this.cid&&t.append("cid",this.cid),location.href="ms-windows-store://pdp/?"+t.toString()}launchStoreAppPdpViaWhitelistedDomain(){var t;const i=null===(t=this.shadowRoot)||void 0===t?void 0:t.querySelector("iframe");if(!p(this,l,"f")&&i&&i.contentWindow){p(this,o,"m",u).call(this);const t={message:"launch",productId:this.productId,cid:this.cid,windowMode:this.windowMode,source:window.location.hostname};i.contentWindow.postMessage(t,"*")}else this.launchFullStoreApp()}launchStoreWebPdp(t){var i="";i=this.cid?`https://apps.microsoft.com/store/detail/${this.productId}?cid=${encodeURIComponent(this.cid)}&referrer=appbadge&source=${encodeURIComponent(window.location.hostname.toLowerCase())}`:`https://apps.microsoft.com/store/detail/${this.productId}?referrer=appbadge&source=${encodeURIComponent(window.location.hostname.toLowerCase())}`,t.ctrlKey?window.open(i,"_blank"):window.location.href=i}static createSupportedLanguages(){let t=new Map;t.set("Afrikaans","af"),t.set("Albanian","sq"),t.set("Amharic","am"),t.set("Arabic","ar"),t.set("Armenian","hy"),t.set("Assamese","as"),t.set("Azerbaijani","az"),t.set("Bengali","bn"),t.set("Bosnian","bs"),t.set("Bulgarian","bg"),t.set("Catalan","ca"),t.set("Chinese_Simplified","zh-cn"),t.set("Chinese_Traditional","zh-tw"),t.set("Croatian","hr"),t.set("Czech","cs"),t.set("Danish","da"),t.set("Dutch","nl"),t.set("English","en-us"),t.set("Estonian","et"),t.set("Filipino","fil"),t.set("Finnish","fi"),t.set("French","fr"),t.set("Galician","gl"),t.set("Georgian","ka"),t.set("German","de"),t.set("Greek","el"),t.set("Gujarati","gu"),t.set("Hebrew","he"),t.set("Hindi","hi"),t.set("Hungarian","hu"),t.set("Icelandic","is"),t.set("Indonesian","id"),t.set("Irish","ga"),t.set("Italian","it"),t.set("Japanese","ja"),t.set("Kannada","kn"),t.set("Kazakh","kk"),t.set("Khmer","km"),t.set("Konkani","kok"),t.set("Korean","ko"),t.set("Lao","lo"),t.set("Latvian","lv"),t.set("Lithuanian","lt"),t.set("Luxembourgish","lb"),t.set("Macedonian","mk"),t.set("Malay","ms"),t.set("Malayalam","ml"),t.set("Maltese","mt"),t.set("Māori","mi"),t.set("Marathi","mr"),t.set("Nepali","ne"),t.set("Norwegian","nn"),t.set("Oriya","or"),t.set("Persian","fa"),t.set("Polish","pl"),t.set("Portuguese_Brazil","pt-br"),t.set("Portuguese_Portugal","pt-pt"),t.set("Punjabi","pa"),t.set("Quechua","quz"),t.set("Romanian","ro"),t.set("Russian","ru"),t.set("Scottish_Gaelic","gd"),t.set("Serbian","sr"),t.set("Slovak","sk"),t.set("Slovenian","sl"),t.set("Spanish","es"),t.set("Swedish","sv"),t.set("Tamil","ta"),t.set("Telugu","te"),t.set("Thai","th"),t.set("Turkish","tr"),t.set("Uighur","ug"),t.set("Ukrainian","uk"),t.set("Urdu","ur"),t.set("Uzbek","uz"),t.set("Vietnamese","vi");let i=[];for(let e of t.keys()){let n={name:e,imageLarge:{fileName:t.get(e).concat(" ").concat("dark.svg")},imageLargeLight:{fileName:t.get(e).concat(" ").concat("light.svg")},code:t.get(e)||""};i.push(n)}return i}}r=g,s=new WeakMap,a=new WeakMap,c=new WeakMap,h=new WeakMap,d=new WeakMap,l=new WeakMap,o=new WeakSet,u=function(){const t="securitypolicyviolation",i=i=>{"frame-src"===i.violatedDirective&&i.type===t&&(m(this,l,!0,"f"),this.launchFullStoreApp())};document.addEventListener(t,i,{once:!0}),setTimeout((()=>document.removeEventListener(t,i)),2e3)},g.englishLanguage={name:"English",code:"en-us",imageLarge:{fileName:"en-us dark.svg"},imageLargeLight:{fileName:"en-us light.svg"}},g.supportedLanguages=r.createSupportedLanguages(),customElements.define("ms-store-badge",g);
2 |
--------------------------------------------------------------------------------
/dist/iframe.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |