Merge pull request #261 from omnivore-app/experiment/appreader
Bundled appreader for iOS
This commit is contained in:
File diff suppressed because one or more lines are too long
16
packages/appreader/.babelrc
Normal file
16
packages/appreader/.babelrc
Normal file
@ -0,0 +1,16 @@
|
||||
{
|
||||
"presets": [
|
||||
"@babel/preset-env",
|
||||
"@babel/preset-react",
|
||||
"@babel/preset-typescript"
|
||||
],
|
||||
"plugins": [
|
||||
[
|
||||
"@babel/plugin-transform-runtime",
|
||||
{
|
||||
"regenerator": true
|
||||
}
|
||||
]
|
||||
]
|
||||
}
|
||||
|
||||
3
packages/appreader/.eslintignore
Normal file
3
packages/appreader/.eslintignore
Normal file
@ -0,0 +1,3 @@
|
||||
**/node_modules/*
|
||||
**/out/*
|
||||
**/.next/*
|
||||
26
packages/appreader/.eslintrc
Normal file
26
packages/appreader/.eslintrc
Normal file
@ -0,0 +1,26 @@
|
||||
{
|
||||
"parser": "@typescript-eslint/parser",
|
||||
"parserOptions": {
|
||||
"project": "tsconfig.json"
|
||||
},
|
||||
"plugins": ["@typescript-eslint", "functional"],
|
||||
"extends": [
|
||||
"next/core-web-vitals",
|
||||
"plugin:@typescript-eslint/recommended",
|
||||
"plugin:@typescript-eslint/eslint-recommended",
|
||||
"prettier",
|
||||
"plugin:functional/no-object-orientation"
|
||||
],
|
||||
"root": true,
|
||||
"env": {
|
||||
"es6": true,
|
||||
"browser": true,
|
||||
"jest": true,
|
||||
"node": true
|
||||
},
|
||||
"ignorePatterns": ["next.config.js", "jest.config.js"],
|
||||
"rules": {
|
||||
"functional/no-mixed-type": 0,
|
||||
"react/react-in-jsx-scope": 0
|
||||
}
|
||||
}
|
||||
9
packages/appreader/additional.d.ts
vendored
Normal file
9
packages/appreader/additional.d.ts
vendored
Normal file
@ -0,0 +1,9 @@
|
||||
export {}
|
||||
|
||||
declare global {
|
||||
interface Window {
|
||||
omnivoreArticle?: any
|
||||
omnivoreEnv?: any
|
||||
fontSize?: number
|
||||
}
|
||||
}
|
||||
51
packages/appreader/index.html
Normal file
51
packages/appreader/index.html
Normal file
@ -0,0 +1,51 @@
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="utf-8" />
|
||||
<meta name='viewport' content='width=device-width, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0, user-scalable=no' />
|
||||
</head>
|
||||
<body>
|
||||
<div id="root">
|
||||
<!-- {{INJECT_SWIFT_STRING_HERE!!}} -->
|
||||
<script type="text/javascript">
|
||||
function loadEnv() {
|
||||
window.omnivoreEnv = {
|
||||
"NEXT_PUBLIC_APP_ENV":"local",
|
||||
"NEXT_PUBLIC_LOCAL_BASE_URL":"http://localhost:3000",
|
||||
"NEXT_PUBLIC_LOCAL_SERVER_BASE_URL":"http://localhost:4000",
|
||||
"NEXT_PUBLIC_LOCAL_HIGHLIGHTS_BASE_URL":"http://localhost:4000"
|
||||
}
|
||||
}
|
||||
|
||||
function loadArticle() {
|
||||
const CONTENT = `
|
||||
<div class="page" id="readability-page-1" data-omnivore-anchor-idx="1"><div data-omnivore-anchor-idx="2">
|
||||
<p data-omnivore-anchor-idx="3">I didn't have time to write a short email so I scheduled a long meeting.</p><p data-omnivore-anchor-idx="4">
|
||||
— <a href="https://twitter.com/jacksonh" data-omnivore-anchor-idx="5">jacksonh</a> Jackson Harper <a href="https://twitter.com/jacksonh/status/1069798258141159425" data-omnivore-anchor-idx="6">December 4, 2018, 3:39 AM UTC</a>
|
||||
</p></div></div>
|
||||
`;
|
||||
|
||||
window.omnivoreArticle = {
|
||||
id: "test",
|
||||
linkId: "test",
|
||||
slug: "test-slug",
|
||||
createdAt: new Date().toISOString(),
|
||||
savedAt: new Date().toISOString(),
|
||||
url: "https://example.com",
|
||||
title: "Test Article",
|
||||
content: CONTENT,
|
||||
originalArticleUrl: "https://example.com",
|
||||
contentReader: "WEB",
|
||||
readingProgressPercent: 0,
|
||||
readingProgressAnchorIndex: 0,
|
||||
highlights: [],
|
||||
}
|
||||
}
|
||||
|
||||
loadEnv()
|
||||
loadArticle()
|
||||
</script>
|
||||
</div>
|
||||
<script src="bundle.js"></script>
|
||||
</body>
|
||||
</html>
|
||||
37
packages/appreader/package.json
Normal file
37
packages/appreader/package.json
Normal file
@ -0,0 +1,37 @@
|
||||
{
|
||||
"name": "@omnivore/appreader",
|
||||
"version": "1.0.0",
|
||||
"private": true,
|
||||
"scripts": {
|
||||
"build": "webpack --mode production"
|
||||
},
|
||||
"dependencies": {
|
||||
"@omnivore/web": "1.0.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
"webpack": "^5.70.0",
|
||||
"webpack-cli": "^4.9.2",
|
||||
"@babel/core": "^7.17.7",
|
||||
"@babel/plugin-transform-runtime": "^7.17.0",
|
||||
"@babel/preset-env": "^7.16.11",
|
||||
"@babel/preset-react": "^7.16.7",
|
||||
"@babel/preset-typescript": "^7.16.7",
|
||||
"@babel/runtime": "^7.17.7",
|
||||
"@types/string-replace-loader": "^2.3.2",
|
||||
"@types/webpack-bundle-analyzer": "^4.4.1",
|
||||
"@types/webpack-dev-server": "^4.7.2",
|
||||
"babel-loader": "^8.2.3",
|
||||
"css-loader": "^6.7.1",
|
||||
"eslint-config-next": "12.0.7",
|
||||
"eslint-plugin-functional": "^4.0.2",
|
||||
"eslint-plugin-react": "^7.28.0",
|
||||
"string-replace-loader": "^3.1.0",
|
||||
"style-loader": "^3.3.1",
|
||||
"webpack-bundle-analyzer": "^4.5.0",
|
||||
"webpack-dev-server": "^4.7.4"
|
||||
},
|
||||
"volta": {
|
||||
"node": "14.18.0",
|
||||
"yarn": "1.22.10"
|
||||
}
|
||||
}
|
||||
43
packages/appreader/src/index.tsx
Normal file
43
packages/appreader/src/index.tsx
Normal file
@ -0,0 +1,43 @@
|
||||
import React from 'react'
|
||||
import ReactDOM from 'react-dom'
|
||||
import { Box, VStack } from '@omnivore/web/components/elements/LayoutPrimitives'
|
||||
import { ArticleContainer } from '@omnivore/web/components/templates/article/ArticleContainer'
|
||||
import { ArticleAttributes } from '@omnivore/web/lib/networking/queries/useGetArticleQuery'
|
||||
import { applyStoredTheme } from '@omnivore/web/lib/themeUpdater'
|
||||
import '@omnivore/web/styles/globals.css'
|
||||
import '@omnivore/web/styles/articleInnerStyling.css'
|
||||
|
||||
const App = () => {
|
||||
applyStoredTheme(false) // false to skip serevr sync
|
||||
|
||||
return (
|
||||
<>
|
||||
<Box
|
||||
css={{
|
||||
overflowY: 'auto',
|
||||
height: '100%',
|
||||
width: '100vw',
|
||||
}}
|
||||
>
|
||||
<VStack
|
||||
alignment="center"
|
||||
distribution="center"
|
||||
className="disable-webkit-callout"
|
||||
>
|
||||
<ArticleContainer
|
||||
viewerUsername="test"
|
||||
article={window.omnivoreArticle as ArticleAttributes}
|
||||
scrollElementRef={React.createRef()}
|
||||
isAppleAppEmbed={true}
|
||||
highlightBarDisabled={true}
|
||||
highlightsBaseURL="https://example.com"
|
||||
fontSize={window.fontSize ?? 18}
|
||||
margin={0}
|
||||
/>
|
||||
</VStack>
|
||||
</Box>
|
||||
</>
|
||||
)
|
||||
}
|
||||
|
||||
ReactDOM.render(<App />, document.getElementById('root'))
|
||||
17
packages/appreader/tsconfig.json
Normal file
17
packages/appreader/tsconfig.json
Normal file
@ -0,0 +1,17 @@
|
||||
{
|
||||
"compilerOptions": {
|
||||
"lib": ["dom", "dom.iterable", "esnext"],
|
||||
"allowJs": true,
|
||||
"allowSyntheticDefaultImports": true,
|
||||
"skipLibCheck": true,
|
||||
"esModuleInterop": true,
|
||||
"strict": true,
|
||||
"forceConsistentCasingInFileNames": true,
|
||||
"moduleResolution": "node",
|
||||
"resolveJsonModule": true,
|
||||
"isolatedModules": true,
|
||||
"noEmit": true,
|
||||
"jsx": "react"
|
||||
},
|
||||
"include": ["additional.d.ts", "src"]
|
||||
}
|
||||
79
packages/appreader/webpack.config.ts
Normal file
79
packages/appreader/webpack.config.ts
Normal file
@ -0,0 +1,79 @@
|
||||
import path from "path"
|
||||
import glob from 'glob'
|
||||
import { DefinePlugin } from 'webpack'
|
||||
import { Configuration } from "webpack"
|
||||
import { BundleAnalyzerPlugin } from 'webpack-bundle-analyzer'
|
||||
|
||||
|
||||
const analyze = process.env.ANALYZE
|
||||
|
||||
const config: Configuration = {
|
||||
entry: {
|
||||
bundle: './src/index.tsx',
|
||||
fonts: [
|
||||
...glob.sync('../web/public/static/fonts/Inter/*'),
|
||||
...glob.sync('../web/public/static/fonts/SFMono/*')
|
||||
],
|
||||
},
|
||||
module: {
|
||||
rules: [
|
||||
{
|
||||
test: /\.(ts|js)x?$/,
|
||||
exclude: /node_modules/,
|
||||
use: {
|
||||
loader: "babel-loader",
|
||||
options: {
|
||||
presets: [
|
||||
"@babel/preset-env",
|
||||
["@babel/preset-react", {"runtime": "automatic"}],
|
||||
"@babel/preset-typescript",
|
||||
],
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
test: /\.css$/i,
|
||||
use: ['style-loader', {
|
||||
loader: 'css-loader',
|
||||
options: { url: false }
|
||||
}, {
|
||||
// We want paths like `/static/fonts/Inter/Inter.woff2 to become
|
||||
// `Inter.woff2` which is how they will be bundled on iOS.
|
||||
loader: 'string-replace-loader',
|
||||
options: {
|
||||
search: '\(\'/static/fonts/.*/(.*)\'\)',
|
||||
replace(_s: string, _p: string, group: string) {
|
||||
return group
|
||||
},
|
||||
flags: 'g',
|
||||
},
|
||||
}],
|
||||
},
|
||||
{
|
||||
test: /.(ttf|otf|woff(2)?)(\?[a-z0-9]+)?$/,
|
||||
type: 'asset/resource',
|
||||
generator: {
|
||||
filename: '[path][name][ext]'
|
||||
}
|
||||
},
|
||||
],
|
||||
},
|
||||
plugins: [
|
||||
new DefinePlugin({
|
||||
'process.env': 'window.omnivoreEnv',
|
||||
}),
|
||||
new BundleAnalyzerPlugin({
|
||||
openAnalyzer: !!analyze,
|
||||
analyzerMode: 'static',
|
||||
})
|
||||
],
|
||||
resolve: {
|
||||
extensions: [".tsx", ".ts", ".js"],
|
||||
},
|
||||
output: {
|
||||
path: path.resolve(__dirname, "build"),
|
||||
filename: '[name].js',
|
||||
},
|
||||
};
|
||||
|
||||
export default config;
|
||||
Reference in New Issue
Block a user