Skip to content

Commit

Permalink
Merge pull request #500 from cofacts/typescript
Browse files Browse the repository at this point in the history
Initialize Typescript
  • Loading branch information
MrOrz committed Feb 2, 2023
2 parents fd84eee + b24cb2a commit 97f01b6
Show file tree
Hide file tree
Showing 25 changed files with 8,462 additions and 628 deletions.
1 change: 1 addition & 0 deletions .babelrc.js
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ module.exports = {
"constants": "./constants",
"pages": "./pages",
"lib": "./lib",
"typegen": "./typegen",
}
}
],
Expand Down
2 changes: 2 additions & 0 deletions .dockerignore
Original file line number Diff line number Diff line change
Expand Up @@ -12,3 +12,5 @@
!ecosystem.config.js
!.storybook/*
!public/*
!pages/*
!typegen/*
16 changes: 14 additions & 2 deletions .eslintrc.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
module.exports = {
parser: '@babel/eslint-parser',
parser: '@typescript-eslint/parser',
extends: [
'eslint:recommended',
'plugin:import/errors',
Expand Down Expand Up @@ -31,7 +31,19 @@ module.exports = {
node: true,
},
settings: {
'import/resolver': { 'babel-module': {} },
'import/resolver': {
'babel-module': {
// For JS files to include TS files also
extensions: ['.js', '.jsx', '.ts', '.tsx'],
},
},
react: { version: 'detect' },
},
overrides: [
{
files: ['**/*.ts', '**/*.tsx'],
extends: ['plugin:@typescript-eslint/recommended'],
plugins: ['@typescript-eslint'],
},
],
};
1 change: 1 addition & 0 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ jobs:
cache: 'npm'
- run: npm ci
- run: npm run lint
- run: npm run typecheck
- run: npm run i18n:validate
- run: npm run test -- --coverage
- name: Update coveralls
Expand Down
24 changes: 24 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -141,6 +141,30 @@ babel cache for the new translation to appear correctly.

When building using Docker, `LOCALE` can be provided via build args.

### Typescript and API types

This repository uses GraphQL Code Generator with [client preset](https://the-guild.dev/graphql/codegen/plugins/presets/preset-client).

When writing Typescript file with GraphQL, please run this command to generate or update the GraphQL codegen result (`TypedDocumentNode` in `typegen/*`):

```bash
$ npm run typegen
```

If encountering GraphQL operations or fragments wrapped with `gql`, please change to codegen result instead:
```typescript
// Old syntax
import gql from 'graphql-tag';

gql`...`;

// New syntax
import { graphql } from 'path-to-typegen';
graphql(/* GraphQL */ `...`)
```

To consume the fragments from typed API, see [Fragment Masking documentation](https://the-guild.dev/graphql/codegen/plugins/presets/preset-client#fragment-masking) of the client preset.

## Legal

`LICENSE` defines the license agreement for the source code in this repository.
Expand Down
19 changes: 19 additions & 0 deletions codegen.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
import { CodegenConfig } from '@graphql-codegen/cli';

const config: CodegenConfig = {
// schema: 'http://localhost:5000/graphql',
schema: 'https://dev-api.cofacts.tw/graphql',
documents: ['pages/**/*.tsx?', 'components/**/*.tsx?', 'lib/**/*.tsx'],
generates: {
'./typegen/': {
preset: 'client',
plugins: [],
presetConfig: {
// Rename useFragment to avoid conflicting with ESLint React hook rule
// https://the-guild.dev/graphql/codegen/plugins/presets/preset-client#embrace-fragment-masking-principles
fragmentMasking: { unmaskFunctionName: 'getFragmentData' },
},
},
},
};
export default config;
4 changes: 2 additions & 2 deletions components/ListPageDisplays/ArticleCard.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ import Infos, { TimeInfo } from 'components/Infos';
import ExpandableText from 'components/ExpandableText';
import Thumbnail from 'components/Thumbnail';
import ListPageCard from './ListPageCard';
import { highlightSections } from 'lib/text';
import { highlightSections, HighlightFields } from 'lib/text';
import { useHighlightStyles } from './utils';
import cx from 'clsx';

Expand Down Expand Up @@ -149,7 +149,7 @@ ArticleCard.fragments = {
}
${Thumbnail.fragments.ThumbnailArticleData}
`,
Highlight: highlightSections.fragments.HighlightFields,
Highlight: HighlightFields,
};

export default ArticleCard;
4 changes: 2 additions & 2 deletions components/ListPageDisplays/ReplyItem.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ import ExpandableText from 'components/ExpandableText';
import ArticleReplySummary from 'components/ArticleReplySummary';
import ArticleReplyFeedbackControl from 'components/ArticleReplyFeedbackControl';
import ReplyInfo from 'components/ReplyInfo';
import { highlightSections } from 'lib/text';
import { highlightSections, HighlightFields } from 'lib/text';
import { useHighlightStyles } from './utils';

const useStyles = makeStyles(theme => ({
Expand Down Expand Up @@ -121,7 +121,7 @@ ReplyItem.fragments = {
${Avatar.fragments.AvatarData}
${ArticleReplySummary.fragments.ArticleReplySummaryData}
`,
Highlight: highlightSections.fragments.HighlightFields,
Highlight: HighlightFields,
};

export default ReplyItem;
4 changes: 2 additions & 2 deletions jest.config.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,8 @@ module.exports = {
// Required by Storyshot multiSnapshotWithOptions()
// Ref: https://github.com/storybookjs/storybook/tree/master/addons/storyshots/storyshots-core#multisnapshotwithoptionsoptions
//
'^.+\\.stories\\.jsx?$': '@storybook/addon-storyshots/injectFileName',
'^.+\\.jsx?$': 'babel-jest',
'^.+\\.stories\\.(j|t)sx?$': '@storybook/addon-storyshots/injectFileName',
'^.+\\.(j|t)sx?$': 'babel-jest',
},
moduleNameMapper: {
// Ignore CSS and image imports in jest
Expand Down
File renamed without changes.
66 changes: 41 additions & 25 deletions lib/__tests__/text.js → lib/__tests__/text.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,12 @@
import React from 'react';
import { linkify, nl2br, truncate, highlightSections } from '../text';
import { makeFragmentData } from '../../typegen';
import {
linkify,
nl2br,
truncate,
highlightSections,
HighlightFields,
} from '../text';

describe('text', () => {
describe('linkify', () => {
Expand Down Expand Up @@ -178,22 +185,28 @@ describe('highlightSections', () => {
it('return empty arrays for empty highlights', () => {
expect(
highlightSections(
{
text: null,
reference: null,
hyperlinks: null,
},
makeFragmentData(
{
text: null,
reference: null,
hyperlinks: null,
},
HighlightFields
),
classes
)
).toMatchInlineSnapshot(`Array []`);

expect(
highlightSections(
{
text: null,
reference: null,
hyperlinks: [],
},
makeFragmentData(
{
text: null,
reference: null,
hyperlinks: [],
},
HighlightFields
),
classes
)
).toMatchInlineSnapshot(`Array []`);
Expand All @@ -202,20 +215,23 @@ describe('highlightSections', () => {
it('wraps <mark> to all highlightable fields', () => {
expect(
highlightSections(
{
text:
'<HIGHLIGHT>Lorem ipsum</HIGHLIGHT> dolor sit <HIGHLIGHT>amet</HIGHLIGHT>, consectetur <HIGHLIGHT>adipiscing elit</HIGHLIGHT>',
reference:
'【誤導】<HIGHLIGHT>大陸東北男子穿短袖短褲晨跑</HIGHLIGHT>?<HIGHLIGHT>凍成人型冰棍影片</HIGHLIGHT>?2018酒醉凍傷致死事件\n\nMyGoPen查證參考:\nhttps://www.mygopen.com/2021/01/freeze-Morning-jogging.html',
hyperlinks: [
{
title:
'<HIGHLIGHT>MyGoPen</HIGHLIGHT>|這是假消息: 【假LINE】大同寶寶貼圖詐騙新手法!連到外部網站再騙你加',
summary:
'今年為一九<HIGHLIGHT>六四</HIGHLIGHT>年以來首度無颱風侵台',
},
],
},
makeFragmentData(
{
text:
'<HIGHLIGHT>Lorem ipsum</HIGHLIGHT> dolor sit <HIGHLIGHT>amet</HIGHLIGHT>, consectetur <HIGHLIGHT>adipiscing elit</HIGHLIGHT>',
reference:
'【誤導】<HIGHLIGHT>大陸東北男子穿短袖短褲晨跑</HIGHLIGHT>?<HIGHLIGHT>凍成人型冰棍影片</HIGHLIGHT>?2018酒醉凍傷致死事件\n\nMyGoPen查證參考:\nhttps://www.mygopen.com/2021/01/freeze-Morning-jogging.html',
hyperlinks: [
{
title:
'<HIGHLIGHT>MyGoPen</HIGHLIGHT>|這是假消息: 【假LINE】大同寶寶貼圖詐騙新手法!連到外部網站再騙你加',
summary:
'今年為一九<HIGHLIGHT>六四</HIGHLIGHT>年以來首度無颱風侵台',
},
],
},
HighlightFields
),
classes
)
).toMatchInlineSnapshot(`
Expand Down
27 changes: 0 additions & 27 deletions lib/gtm.js

This file was deleted.

27 changes: 27 additions & 0 deletions lib/gtm.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
import { useEffect } from 'react';

/**
* Google tag manager related utility functions
*/

/**
* @param args - data to feed to dataLayer.push
*/
export function pushToDataLayer(...args: unknown[]) {
if (typeof window === 'undefined') return; // Skip in SSR

if (!('dataLayer' in window)) window['dataLayer'] = [];
window['dataLayer'].push(...args);
}

/**
* @param trigger - trigger useEffect() after trigger turns truthy
* @param args - data to send to pushDataLayer on trigger change
*/
export function usePushToDataLayer(trigger: unknown, args: object) {
const dontTrigger = !trigger;
useEffect(() => {
if (dontTrigger) return;
pushToDataLayer(args);
}, [dontTrigger, args]);
}
10 changes: 9 additions & 1 deletion lib/isUserBlocked.js → lib/isUserBlocked.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,11 @@ const COOKIE_KEY = 'isUserBlocked';
const COOKIE_TRUE_VALUE = '1';
const isUserBlockedContext = React.createContext(false);

type Props = {
serverSideCookie?: object;
children: React.ReactNode;
};

/**
* The context provider for decendents to read if the current browser belongs to a blocked user.
* It reads from an independent cookie so that it remains true even after the blocked user is logged
Expand All @@ -19,7 +24,10 @@ const isUserBlockedContext = React.createContext(false);
* @param {Object?} props.serverSideCookie - the cookie from server side, set by _document.js
* @returns {React.Provider<boolean>}
*/
export function IsUserBlockedProvider({ serverSideCookie, children }) {
export function IsUserBlockedProvider({
serverSideCookie,
children,
}: Props): React.ReactElement {
const { Provider } = isUserBlockedContext;
const cookieValue = serverSideCookie
? serverSideCookie[COOKIE_KEY]
Expand Down
Loading

0 comments on commit 97f01b6

Please sign in to comment.