mirror of
https://github.com/omnivore-app/omnivore.git
synced 2026-03-11 08:54:26 +00:00
WIP: bundled appreader for iOS
Update webpack to bundle fonts and CSS Remove special font handling Add package.json allow setting the article data on window so it can be set in index.html Add window omnivoreArticle definition Remove unused dependencies remove unused copy-webpack plugin dep Remove unused deps Handle setting the environment dynamically from Swift Remove unused deps Remove more unused deps Update index, dont use subfolders for fonts Use a regex to replace font url patterns Remove local apple changes
This commit is contained in:
parent
c24bc3b136
commit
059389bbe8
9 changed files with 294 additions and 0 deletions
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/build/index.html
Normal file
51
packages/appreader/build/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"
|
||||
}
|
||||
}
|
||||
56
packages/appreader/src/index.tsx
Normal file
56
packages/appreader/src/index.tsx
Normal file
|
|
@ -0,0 +1,56 @@
|
|||
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 '@omnivore/web/styles/globals.css'
|
||||
import '@omnivore/web/styles/articleInnerStyling.css'
|
||||
|
||||
const App = () => {
|
||||
var themeId = window.localStorage.getItem('theme')
|
||||
|
||||
if (themeId) {
|
||||
document.body.classList.remove(
|
||||
'theme-default',
|
||||
'White',
|
||||
'Gray',
|
||||
'LightGray',
|
||||
'Dark'
|
||||
)
|
||||
document.body.classList.add(themeId)
|
||||
}
|
||||
|
||||
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={false}
|
||||
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;
|
||||
Loading…
Reference in a new issue