Skip to content

Commit f30d93a

Browse files
committed
resolve conflict
2 parents d750737 + 52d011c commit f30d93a

447 files changed

Lines changed: 11920 additions & 12409 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.
Lines changed: 82 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,82 @@
1+
#!/bin/bash
2+
3+
# Checks for usage of iframe and non-cloudflare URL for videos in documentation.
4+
# Assumes that Jekyll markdown documents compile and render correctly, i.e.
5+
# no malformed HTML tags or liquid tags.
6+
set -eu
7+
8+
source ./scripts/shellUtils.sh
9+
title "Enforce no iframe usage for videos and cloudflare CDN links"
10+
HAS_VIOLATION=false
11+
12+
# Use diff to find all changed markdown files in the docs/ directory compared
13+
# the current HEAD commit on main. This will mirror behavior on the workflow
14+
# when the local copy of origin/main is up-to-date. We exclude the README.md
15+
# files from linting.
16+
CHANGED_FILES="$(git diff origin/main..HEAD --name-only --diff-filter=MAR -- ':docs/*.md' ':(exclude,icase)*README.md')"
17+
18+
# RegEx to match the opening iframe tags.
19+
# Matches iframes like: <iframe src="https://myembeddedvideo.com" allowfullscreen width="10" height="10" allow="autoplay">
20+
# Broken into 2 consecutive non-capturing groups "(?:[...])".
21+
# Non-capturing groups are part of the matching pattern, but not returned in matches.
22+
# First Group: "<iframe[^>]*?"
23+
# - Checks for the iframe opening tag <iframe, and "[^>]*" non-greedily
24+
# consumes characters except for ">" (as few characters as possible
25+
# upto the closing tag).
26+
# Second Group: OR of three attribute tags "(\s*width|\s*height|\s*src)+"
27+
# - This "+" checks for at least one of the attributes in the group, in any order.
28+
# This is what we use to check if it's an embed.
29+
# - Each attribute tag consists of a named capturing group that saves quoted value
30+
# after the "=":
31+
# - [\"\"'](?<width>[^\"\"']+)[\"\"']
32+
# This matches the opening quotation marks followed by the named capturing
33+
# group (?<width>[....]) and the [^\"\"'] matches any character that isn't
34+
# a closing quotation mark. This doesn't allow for empty width attribute.
35+
# Followed by the closing quotation mark.
36+
# Finally, [^>]*? consumes all remaining characters after the attributes and
37+
# closes the iframe tag with ">". We consider there to be an iframe in the file
38+
# if all this is satisfied.
39+
REGEX="(?:<iframe[^>]*?)(?:\s*width=[\"\"'](?<width>[^\"\"']+)[\"\"']|\s*height=[\"\"'](?<height>[^'\"\"]+)[\"\"']|\s*src=[\"\"'](?<src>[^'\"\"]+[\"\"']))+[^>]*?>"
40+
while IFS= read -r FILE; do
41+
while IFS= read -r MATCH; do
42+
error "$FILE:$MATCH Do not use iframes for video embeds."
43+
HAS_VIOLATION=true
44+
done < <(pcregrep -n "$REGEX" "$FILE")
45+
done <<< "$CHANGED_FILES"
46+
47+
# RegEx to match liquid Jekyll tag for included videos, and extracts the src.
48+
# Matches includes like: {% include video.html src="https://incorrectlyembeddedvideo.com" %}
49+
#
50+
# The regex begins by checking for the opening "{% include video.html" with any
51+
# white spacing that wouldn't break the liquid tag. Followed by some white space.
52+
#
53+
# Next we have one non-capturing group "(?:[...])+" for attributes "thumbnail=..." and "src=....".
54+
# We expect at least one of these elements to appear.
55+
# Each attribute is formatted as: \s*ATTR=[\"\"'](?<ATTR>[^\"\"']+)[\"\"']
56+
# - This is zero or more whitespace followed by the opening "ATTR=", opening
57+
# quotes with non-empty string inside, and closing quotes. We capture the
58+
# value of the attribute using a named capturing group "(?<ATTR>[...])".
59+
# The attribute is closed then with some closing quotation marks "[\"\"']".
60+
# We close the regex with optional white space and ending %}. We extract
61+
REGEX="{%\s*include\s+video\.html\s+(?:\s*thumbnail=[\"\"'](?<thumbnail>[^'\"\"]+)[\"\"']|\s*src=[\"\"'](?<src>[^'\"\"]+[\"\"']))+\s*%}"
62+
63+
# RegEx to match a cloudflare CDN URL. Expects leading customer number and trailing content ID.
64+
# We match the "https://" followed by some subdomain "(?:\S+)" of alphanumeric-characters
65+
# usually customer information, then ".cloudflarestream.com/" and the optional trailing
66+
# remaining characters "(?:\S*)" usually content ID.
67+
CDN_REGEX="https:\/\/(?:\S+)\.cloudflarestream\.com\/(?:\S*)"
68+
while IFS= read -r FILE; do
69+
while IFS= read -r MATCH; do
70+
if ! echo "$MATCH" | pcregrep -q "$CDN_REGEX"; then
71+
error "$FILE:$MATCH Video URL must be from Cloudflare CDN."
72+
HAS_VIOLATION=true
73+
fi
74+
done < <(pcregrep -n "$REGEX" "$FILE")
75+
done <<< "$CHANGED_FILES"
76+
77+
if [[ $HAS_VIOLATION == true ]]; then
78+
error "Documentation has video violations"
79+
exit 1
80+
fi
81+
82+
success "No violations."

.github/workflows/deployExpensifyHelp.yml

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,9 @@ jobs:
3737
with:
3838
fetch-depth: 0
3939

40+
- name: Install pcregrep
41+
run: sudo apt-get install -y pcregrep
42+
4043
- name: Setup NodeJS
4144
uses: ./.github/actions/composite/setupNode
4245

@@ -48,6 +51,9 @@ jobs:
4851

4952
- name: Enforce that a redirect link has been created
5053
run: ./.github/scripts/enforceRedirect.sh
54+
55+
- name: Enforce iframe and Cloudflare CDN usage
56+
run: ./.github/scripts/enforceVideoFormats.sh
5157

5258
- name: Build with Jekyll
5359
uses: actions/jekyll-build-pages@0143c158f4fa0c5dcd99499a5d00859d79f70b0e

.github/workflows/presubmit.yml

Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,51 @@
1+
name: PR Presubmit Reviews
2+
3+
permissions:
4+
contents: read
5+
pull-requests: write
6+
7+
on:
8+
pull_request:
9+
types: [opened, synchronize, labeled]
10+
pull_request_review_comment:
11+
types: [created]
12+
13+
jobs:
14+
review:
15+
runs-on: ubuntu-latest
16+
if: contains(github.event.pull_request.labels.*.name, 'AI Review')
17+
steps:
18+
- name: Checkout code
19+
uses: actions/checkout@v4
20+
21+
- name: Check required secrets
22+
run: |
23+
if [ -z "${{ secrets.LLM_API_KEY }}" ]; then
24+
echo "Error: LLM_API_KEY secret is not configured"
25+
exit 1
26+
fi
27+
28+
- name: Read RULES.md
29+
id: read-rules
30+
run: |
31+
RULES_CONTENT=$(cat "contributingGuides/review/RULES.md")
32+
{
33+
echo "content<<EOF"
34+
echo "$RULES_CONTENT"
35+
echo "EOF"
36+
} >> "$GITHUB_OUTPUT"
37+
38+
- name: Print RULES.md
39+
run: |
40+
echo "📋 RULES.md"
41+
echo "======================================"
42+
echo "${{ steps.read-rules.outputs.content }}"
43+
echo "======================================"
44+
45+
- uses: aldo-expensify/ai-reviewer-hackaton@c91b349b41efdf1eeaa290716628d76068148f0b
46+
env:
47+
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
48+
LLM_API_KEY: ${{ secrets.LLM_API_KEY }}
49+
LLM_MODEL: "claude-3-7-sonnet-20250219"
50+
with:
51+
style_guide_rules: ${{ steps.read-rules.outputs.content }}

.gitignore

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -153,3 +153,6 @@ react-compiler-output.txt
153153

154154
# Generated by bob (for Nitro modules)
155155
modules/*/lib/
156+
157+
# Claude Code files
158+
.claude/

.storybook/preview.tsx

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,8 @@ import HTMLEngineProvider from '@src/components/HTMLEngineProvider';
1010
import {LocaleContextProvider} from '@src/components/LocaleContextProvider';
1111
import {EnvironmentProvider} from '@src/components/withEnvironment';
1212
import {KeyboardStateProvider} from '@src/components/withKeyboardState';
13+
import CONST from '@src/CONST';
14+
import IntlStore from '@src/languages/IntlStore';
1315
import ONYXKEYS from '@src/ONYXKEYS';
1416
import './fonts.css';
1517

@@ -20,6 +22,8 @@ Onyx.init({
2022
},
2123
});
2224

25+
IntlStore.load(CONST.LOCALES.EN);
26+
2327
const decorators = [
2428
(Story: React.ElementType) => (
2529
<ComposeProviders

Mobile-Expensify

__mocks__/@ua/react-native-airship.ts

Lines changed: 1 addition & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -6,13 +6,6 @@ enum EventType {
66
PushReceived = 'com.airship.push_received',
77
}
88

9-
// eslint-disable-next-line no-restricted-syntax
10-
enum PermissionStatus {
11-
Granted = 'granted',
12-
Denied = 'denied',
13-
NotDetermined = 'not_determined',
14-
}
15-
169
// eslint-disable-next-line @typescript-eslint/no-namespace
1710
namespace iOS {
1811
/**
@@ -78,4 +71,4 @@ const Airship: Partial<AirshipRoot> = {
7871

7972
export default Airship;
8073

81-
export {EventType, iOS, PermissionStatus};
74+
export {EventType, iOS};

android/app/build.gradle

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -114,8 +114,8 @@ android {
114114
minSdkVersion rootProject.ext.minSdkVersion
115115
targetSdkVersion rootProject.ext.targetSdkVersion
116116
multiDexEnabled rootProject.ext.multiDexEnabled
117-
versionCode 1009018904
118-
versionName "9.1.89-4"
117+
versionCode 1009019201
118+
versionName "9.1.92-1"
119119
// Supported language variants must be declared here to avoid from being removed during the compilation.
120120
// This also helps us to not include unnecessary language variants in the APK.
121121
resConfigs "en", "es"

0 commit comments

Comments
 (0)