Compare commits

..

31 Commits

Author SHA1 Message Date
Abdullah Atta
e5ad405a23 Merge pull request #8754 from streetwriters/release/3.3.1
Release v3.3.1
2025-10-10 18:12:40 +05:00
Abdullah Atta
cd1b78d8df ci: fix desktop builds 2025-10-10 17:53:41 +05:00
Abdullah Atta
3b1ca46945 web: fix desktop tests 2025-10-10 16:23:11 +05:00
Abdullah Atta
96c1636f88 web: bump version to 3.3.1 2025-10-10 15:54:29 +05:00
Abdullah Atta
9ff4757ed6 Merge pull request #8753 from streetwriters/fix/make-table-with-adjustable
Make table width adjustable
2025-10-10 15:52:26 +05:00
Abdullah Atta
17c1e77f54 editor: make table width adjustable 2025-10-10 15:47:05 +05:00
Abdullah Atta
187a2a7262 Merge pull request #8735 from 01zulfi/editor/restrict-pasting-premium-features
editor: restrict pasting premium features
2025-10-10 15:38:11 +05:00
Abdullah Atta
4621230549 Merge pull request #8751 from streetwriters/fix/discount-price-on-checkout
Fix discounted price in checkout
2025-10-10 15:33:42 +05:00
Abdullah Atta
d7cb3317a2 web: fix discounted price in checkout 2025-10-10 15:09:41 +05:00
01zulfi
6d81f26864 editor: restrict pasting premium features
Signed-off-by: 01zulfi <85733202+01zulfi@users.noreply.github.com>
2025-10-08 13:31:24 +05:00
Abdullah Atta
2341293d92 Merge pull request #8734 from 01zulfi/common/fix-paragraph-keybinding
common: fix insert paragraph keybinding
2025-10-08 13:20:32 +05:00
Abdullah Atta
215387f8a9 Merge pull request #8731 from streetwriters/chore/get-rid-of-nx
Get rid of nx
2025-10-08 13:20:00 +05:00
01zulfi
534b8c5ad0 common: fix insert paragraph keybinding
Signed-off-by: 01zulfi <85733202+01zulfi@users.noreply.github.com>
2025-10-08 11:57:42 +05:00
Abdullah Atta
b7b2ead9eb setup(tx): minor refactor 2025-10-08 10:57:58 +05:00
Abdullah Atta
b3e34d68e1 setup(tx): add support for passing flags down to commands 2025-10-08 10:55:52 +05:00
Abdullah Atta
39079612aa docs: remove mention of Nx from README 2025-10-08 10:29:18 +05:00
Abdullah Atta
be1af3111f setup: add support for passing args down to command 2025-10-08 10:28:02 +05:00
Abdullah Atta
8dcff49797 core: fix flaky note history tests 2025-10-08 10:27:43 +05:00
Abdullah Atta
687fb4e105 setup: remove editor-mobile from build all exclusion filter 2025-10-08 09:57:40 +05:00
Abdullah Atta
25ae780ad8 ci: get rid of NX_CLOUD_ACCESS_TOKEN 2025-10-08 09:49:05 +05:00
Abdullah Atta
b695367e6c global: add dotenv package 2025-10-08 09:34:59 +05:00
Abdullah Atta
bb274a84fe ci: use node v22 2025-10-08 08:56:20 +05:00
Abdullah Atta
364dccbf7a global: get rid of nx 2025-10-08 08:42:00 +05:00
Ammar Ahmed
110534edec Merge pull request #8714 from streetwriters/fix-mobile-client-selfhosted
Fix mobile client selfhosted
2025-10-06 12:40:26 +05:00
Ammar Ahmed
00e2190b2d Merge pull request #8713 from streetwriters/mobile-fix-legacy-pro-users
mobile: add support for LEGACY_PRO subscription plan name
2025-10-06 12:40:10 +05:00
Ammar Ahmed
e5c3fc667e Merge pull request #8712 from streetwriters/mobile-refactor-e2e-tests
mobile: refactor e2e tests
2025-10-06 12:39:57 +05:00
Abdullah Atta
f76e0b7931 Merge pull request #8711 from 01zulfi/web/ignore-autobackup-notice-when-ignored
web: don't show auto-backup notice again after dismissal
2025-10-06 11:39:35 +05:00
Ammar Ahmed
0457e4417f mobile: minor cleanup 2025-10-06 11:10:19 +05:00
Ammar Ahmed
dae8b5c542 mobile: hide pricing flows on self hosted clients 2025-10-06 10:58:39 +05:00
01zulfi
60107dd77f web: don't show auto-backup notice again after dismissal
Signed-off-by: 01zulfi <85733202+01zulfi@users.noreply.github.com>
2025-10-06 10:24:46 +05:00
Ammar Ahmed
4f3e19aaa2 mobile: add support for LEGACY_PRO subscription plan name 2025-10-06 09:55:28 +05:00
64 changed files with 4419 additions and 5495 deletions

View File

@@ -7,7 +7,7 @@ runs:
- name: Setup Node
uses: actions/setup-node@v4
with:
node-version: 20.x
node-version: 22.x
cache: "npm"
cache-dependency-path: |
package-lock.json

View File

@@ -52,7 +52,6 @@ jobs:
echo "USER_PASSWORD=${{ secrets.USER_PASSWORD }}" >> $GITHUB_ENV
echo "USER_TOTP_SECRET=${{ secrets.USER_TOTP_SECRET }}" >> $GITHUB_ENV
echo "USER_HASHED_PASSWORD=${{ secrets.USER_HASHED_PASSWORD }}" >> $GITHUB_ENV
echo "NX_CLOUD_ACCESS_TOKEN=${{ secrets.NX_CLOUD_ACCESS_TOKEN }}" >> $GITHUB_ENV
- name: Run all @notesnook/core tests
run: npx nx test:e2e @notesnook/core
run: npm run tx @notesnook/core:test:e2e

View File

@@ -65,17 +65,13 @@ jobs:
npm i --cpu x64 sqlite-better-trigram
working-directory: ./apps/desktop
- name: Setup environment
run: |
echo "NX_CLOUD_ACCESS_TOKEN=${{ secrets.NX_CLOUD_ACCESS_TOKEN }}" >> $GITHUB_ENV
- name: Generate desktop build (stable)
if: ${{ inputs.release-track == 'stable' }}
run: npx nx build:desktop @notesnook/web
run: npm run tx @notesnook/web:build:desktop
- name: Generate desktop build (beta)
if: ${{ inputs.release-track == 'beta' }}
run: BETA=true npx nx build:desktop @notesnook/web
run: BETA=true npm run tx @notesnook/web:build:desktop
- name: Build desktop bundle
working-directory: ./apps/desktop
@@ -199,9 +195,9 @@ jobs:
CSC_LINK: ${{ secrets.mac_certs }}
CSC_KEY_PASSWORD: ${{ secrets.mac_certs_password }}
run: |
npx nx run release --project @notesnook/desktop -- --variant=mas
npm run tx @notesnook/desktop:release -- --variant=mas
cd apps/desktop
yarn electron-builder --config=electron-builder.config.js --mac mas --universal -p never
working-directory: ./apps/desktop
- name: Build zip and dmg
env:
@@ -212,13 +208,13 @@ jobs:
APPLE_API_KEY_ID: ${{ secrets.api_key_id }}
APPLE_API_ISSUER: ${{ secrets.api_key_issuer_id }}
run: |
npx nx run release --project @notesnook/desktop
npm run tx @notesnook/desktop:release
cd apps/desktop
if [ ${{ inputs.publish-github }} == true ]; then
yarn electron-builder --config=electron-builder.config.js --mac zip dmg --arm64 --x64 -p always
else
yarn electron-builder --config=electron-builder.config.js --mac zip dmg --arm64 --x64 -p never
fi
working-directory: ./apps/desktop
- name: Deploy to Testflight
if: inputs.publish-apple && steps.appstore.outputs.app-version-latest != steps.app_metadata.outputs.app_version
@@ -271,8 +267,7 @@ jobs:
working-directory: ./apps/desktop
- name: Build Electron wrapper
run: npx nx run release --project @notesnook/desktop
working-directory: ./apps/desktop
run: npm run tx @notesnook/desktop:release
- name: Build snap
if: inputs.publish-snap
@@ -339,8 +334,7 @@ jobs:
working-directory: ./apps/desktop
- name: Build Electron wrapper
run: npx nx run release --project @notesnook/desktop
working-directory: ./apps/desktop
run: npm run tx @notesnook/desktop:release
# - name: Build snap
# if: inputs.publish-snap

View File

@@ -33,12 +33,8 @@ jobs:
npm ci --ignore-scripts --prefer-offline --no-audit
npm run bootstrap -- --scope=web
- name: Setup environment
run: |
echo "NX_CLOUD_ACCESS_TOKEN=${{ secrets.NX_CLOUD_ACCESS_TOKEN }}" >> $GITHUB_ENV
- name: Generate desktop build
run: npx nx build:desktop @notesnook/web
run: npm run tx @notesnook/web:build:desktop
- name: Archive build artifact
uses: actions/upload-artifact@v4
@@ -70,8 +66,7 @@ jobs:
npm run bootstrap -- --scope=desktop
- name: Build Electron wrapper
run: npx nx run release --project @notesnook/desktop
working-directory: ./apps/desktop
run: npm run tx @notesnook/desktop:release
- name: Build app
run: |
@@ -114,8 +109,7 @@ jobs:
npm run bootstrap -- --scope=desktop
- name: Build Electron wrapper
run: npx nx run release --project @notesnook/desktop
working-directory: ./apps/desktop
run: npm run tx @notesnook/desktop:release
- name: Build app
run: |
@@ -164,8 +158,7 @@ jobs:
working-directory: ./apps/desktop
- name: Build Electron wrapper
run: npx nx run release --project @notesnook/desktop
working-directory: ./apps/desktop
run: npm run tx @notesnook/desktop:release
- name: Build app
run: |

View File

@@ -38,12 +38,8 @@ jobs:
npm ci --ignore-scripts --prefer-offline --no-audit
npm run bootstrap -- --scope=editor
- name: Setup environment
run: |
echo "NX_CLOUD_ACCESS_TOKEN=${{ secrets.NX_CLOUD_ACCESS_TOKEN }}" >> $GITHUB_ENV
- name: Build editor
run: npx nx build @notesnook/editor
run: npm run tx @notesnook/editor:build
- name: Run all @notesnook/editor tests
run: npx nx test @notesnook/editor
run: npm run tx @notesnook/editor:test

View File

@@ -25,7 +25,7 @@ jobs:
npm run bootstrap -- --scope=mobile
- name: Build packages
run: npx nx run @notesnook/mobile:build
run: npm run tx @notesnook/mobile:build
- name: ccache
uses: hendrikmuhs/ccache-action@v1.2.11

View File

@@ -39,7 +39,7 @@ jobs:
echo ::set-output name=app_version::$(cat package.json | jq -r .version)
- name: Generate build
run: npx nx build @notesnook/monograph
run: npm run tx @notesnook/monograph:build
# Setup Buildx
- name: Docker Setup Buildx

View File

@@ -20,7 +20,6 @@ jobs:
- name: Setup environment
run: |
echo "NX_CLOUD_ACCESS_TOKEN=${{ secrets.NX_CLOUD_ACCESS_TOKEN }}" >> $GITHUB_ENV
echo "CLOUDFLARE_ACCOUNT_ID=${{ secrets.CLOUDFLARE_ACCOUNT_ID }}" >> $GITHUB_ENV
echo "CLOUDFLARE_API_TOKEN=${{ secrets.CLOUDFLARE_API_TOKEN }}" >> $GITHUB_ENV

View File

@@ -20,7 +20,6 @@ jobs:
- name: Setup environment
run: |
echo "NX_CLOUD_ACCESS_TOKEN=${{ secrets.NX_CLOUD_ACCESS_TOKEN }}" >> $GITHUB_ENV
echo "CLOUDFLARE_ACCOUNT_ID=${{ secrets.CLOUDFLARE_ACCOUNT_ID }}" >> $GITHUB_ENV
echo "CLOUDFLARE_API_TOKEN=${{ secrets.CLOUDFLARE_API_TOKEN }}" >> $GITHUB_ENV

View File

@@ -27,10 +27,6 @@ jobs:
npm ci --ignore-scripts --prefer-offline --no-audit
npm run bootstrap -- --scope=web
- name: Setup environment
run: |
echo "NX_CLOUD_ACCESS_TOKEN=${{ secrets.NX_CLOUD_ACCESS_TOKEN }}" >> $GITHUB_ENV
- name: Build
run: npm run build:web

View File

@@ -30,7 +30,6 @@ jobs:
- name: Setup environment
run: |
echo "NX_CLOUD_ACCESS_TOKEN=${{ secrets.NX_CLOUD_ACCESS_TOKEN }}" >> $GITHUB_ENV
echo "CLOUDFLARE_ACCOUNT_ID=${{ secrets.CLOUDFLARE_ACCOUNT_ID }}" >> $GITHUB_ENV
echo "CLOUDFLARE_API_TOKEN=${{ secrets.CLOUDFLARE_API_TOKEN }}" >> $GITHUB_ENV

View File

@@ -49,10 +49,6 @@ jobs:
npm ci --ignore-scripts --prefer-offline --no-audit
npm run bootstrap -- --scope=web
- name: Setup environment
run: |
echo "NX_CLOUD_ACCESS_TOKEN=${{ secrets.NX_CLOUD_ACCESS_TOKEN }}" >> $GITHUB_ENV
- name: Generate test build
run: npm run build:test:web

View File

@@ -27,7 +27,6 @@ Notesnook is built using the following technologies:
3. React Native — For mobile apps we are using React Native
4. Electron — For desktop app
5. NPM — listed here because we **don't** use Yarn or PNPM or XYZ across any of our projects.
6. Nx — maintaining monorepos is hard but Nx makes it easier.
> **Note: Each project in the monorepo contains its own architecture details which you can refer to.**

File diff suppressed because it is too large Load Diff

View File

@@ -2,7 +2,7 @@
"name": "@notesnook/desktop",
"productName": "Notesnook",
"description": "Your private note taking space",
"version": "3.3.0",
"version": "3.3.1",
"appAppleId": "1544027013",
"private": true,
"main": "./dist/cjs/index.js",

View File

@@ -19,14 +19,11 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
import { strings } from "@notesnook/intl";
import { useThemeColors } from "@notesnook/theme";
import { useRoute } from "@react-navigation/native";
import React, { useEffect, useState } from "react";
import {
ScrollView,
TouchableOpacity,
View,
useWindowDimensions
} from "react-native";
import { TouchableOpacity, View, useWindowDimensions } from "react-native";
import { SheetManager } from "react-native-actions-sheet";
import { KeyboardAwareScrollView } from "react-native-keyboard-aware-scroll-view";
import { DDS } from "../../services/device-detection";
import { eSendEvent } from "../../services/event-manager";
import Navigation from "../../services/navigation";
@@ -47,8 +44,7 @@ import { hideAuth } from "./common";
import { ForgotPassword } from "./forgot-password";
import { AuthHeader } from "./header";
import { useLogin } from "./use-login";
import { useRoute } from "@react-navigation/native";
import { KeyboardAwareScrollView } from "react-native-keyboard-aware-scroll-view";
import SettingsService from "../../services/settings";
const LoginSteps = {
emailAuth: 1,
@@ -81,7 +77,7 @@ export const Login = ({ changeMode }) => {
}
}, 5000);
if (!PremiumService.get()) {
if (!PremiumService.get() && !SettingsService.getProperty("serverUrls")) {
Navigation.navigate("PayWall", {
context: "signup",
state: route.params.state,

View File

@@ -19,6 +19,7 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
import { strings } from "@notesnook/intl";
import { useThemeColors } from "@notesnook/theme";
import { useRoute } from "@react-navigation/native";
import React, { useRef, useState } from "react";
import { TouchableOpacity, View, useWindowDimensions } from "react-native";
import { KeyboardAwareScrollView } from "react-native-keyboard-aware-scroll-view";
@@ -38,7 +39,6 @@ import Heading from "../ui/typography/heading";
import Paragraph from "../ui/typography/paragraph";
import { AuthHeader } from "./header";
import { SignupContext } from "./signup-context";
import { useRoute } from "@react-navigation/native";
const SignupSteps = {
signup: 0,
@@ -91,11 +91,13 @@ export const Signup = ({ changeMode, welcome }) => {
setLastSynced(await db.lastSynced());
clearMessage();
setEmailVerifyMessage();
Navigation.navigate("PayWall", {
canGoBack: false,
state: route.params.state,
context: "signup"
});
if (!SettingsService.getProperty("serverUrls")) {
Navigation.navigate("PayWall", {
canGoBack: false,
state: route.params.state,
context: "signup"
});
}
return true;
} catch (e) {
setCurrentStep(SignupSteps.signup);

View File

@@ -60,6 +60,7 @@ import usePricingPlans, {
PricingPlan
} from "../../hooks/use-pricing-plans";
import Navigation, { NavigationProps } from "../../services/navigation";
import PremiumService from "../../services/premium";
import { getElevationStyle } from "../../utils/elevation";
import { openLinkInBrowser } from "../../utils/functions";
import { AppFontSize, defaultBorderRadius } from "../../utils/size";
@@ -74,7 +75,6 @@ import { IconButton } from "../ui/icon-button";
import { SvgView } from "../ui/svg";
import Heading from "../ui/typography/heading";
import Paragraph from "../ui/typography/paragraph";
import PremiumService from "../../services/premium";
const Steps = {
select: 1,
@@ -114,15 +114,8 @@ const PayWall = (props: NavigationProps<"PayWall">) => {
routeParams.state?.planId,
routeParams.state?.productId
);
console.log(
"selectPlan",
routeParams.state?.planId,
routeParams.state?.productId,
(pricingPlans.selectedProduct as any).productId
);
}
setStep(Steps.buy);
console.log("Buy step");
}
}, [routeParams.state]);
@@ -949,7 +942,6 @@ const PricingPlanCard = ({
regionalDiscount?.sku ||
`notesnook.${plan.id}.${annualBilling ? "yearly" : "monthly"}`
];
console.log(regionalDiscount?.sku);
const price = pricingPlans?.getPrice(
product as RNIap.Subscription,
pricingPlans.hasTrialOffer(plan.id, product?.productId) ? 1 : 0,
@@ -962,6 +954,7 @@ const PricingPlanCard = ({
);
useEffect(() => {
if (pricingPlans?.isGithubRelease) return;
pricingPlans
?.getRegionalDiscount(
plan.id,
@@ -980,7 +973,7 @@ const PricingPlanCard = ({
pricingPlans.isSubscribed();
const isNotReady =
pricingPlans?.loadingPlans || (!price && !WebPlan?.price.gross);
pricingPlans?.loadingPlans || (!price && !WebPlan?.price?.gross);
return (
<TouchableOpacity
@@ -1112,7 +1105,7 @@ const PricingPlanCard = ({
</View>
</View>
{pricingPlans?.loadingPlans || (!price && !WebPlan?.price.gross) ? (
{pricingPlans?.loadingPlans || (!price && !WebPlan?.price?.gross) ? (
<ActivityIndicator size="small" color={colors.primary.accent} />
) : (
<View>
@@ -1120,7 +1113,7 @@ const PricingPlanCard = ({
{isFreePlan
? "0.00"
: price ||
`${WebPlan?.price.currency} ${WebPlan?.price.gross}`}{" "}
`${WebPlan?.price?.currency} ${WebPlan?.price?.gross}`}{" "}
<Paragraph>/{strings.month()}</Paragraph>
</Paragraph>

View File

@@ -15,6 +15,7 @@ import {
} from "../../../services/event-manager";
import Navigation from "../../../services/navigation";
import PremiumService from "../../../services/premium";
import SettingsService from "../../../services/settings";
import { useUserStore } from "../../../stores/use-user-store";
import { eCloseSheet } from "../../../utils/events";
import { AppFontSize } from "../../../utils/size";
@@ -37,7 +38,6 @@ export default function PaywallSheet<Tid extends FeatureId>(props: {
const { colors } = useThemeColors();
const pricingPlans = usePricingPlans();
useEffect(() => {
console.log("PaywallSheet mounted with feature:", props.feature);
ToastManager.hide();
if (!props.feature.availableOn) return;
const plan = pricingPlans.pricingPlans.find(
@@ -55,11 +55,11 @@ export default function PaywallSheet<Tid extends FeatureId>(props: {
}, []);
const isSubscribedOnWeb =
(PremiumService.get() &&
PremiumService.get() &&
(pricingPlans.user?.subscription?.provider ===
SubscriptionProvider.PADDLE ||
pricingPlans.user?.subscription?.provider ===
SubscriptionProvider.PADDLE) ||
pricingPlans.user?.subscription?.provider ===
SubscriptionProvider.STREETWRITERS;
SubscriptionProvider.STREETWRITERS);
const isCurrentPlatform =
(pricingPlans.user?.subscription?.provider === SubscriptionProvider.APPLE &&
@@ -194,25 +194,28 @@ export default function PaywallSheet<Tid extends FeatureId>(props: {
width: "100%"
}}
onPress={() => {
if (
pricingPlans.user?.subscription.plan ===
SubscriptionPlan.LEGACY_PRO ||
!isCurrentPlatform
) {
ToastManager.show({
message: strings.cannotChangePlan(),
context: "local"
});
return;
if (PremiumService.get()) {
if (
pricingPlans.user?.subscription.plan ===
SubscriptionPlan.LEGACY_PRO ||
!isCurrentPlatform
) {
ToastManager.show({
message: strings.cannotChangePlan(),
context: "local"
});
return;
}
if (isSubscribedOnWeb) {
ToastManager.show({
message: strings.changePlanOnWeb(),
context: "local"
});
return;
}
}
if (isSubscribedOnWeb) {
ToastManager.show({
message: strings.changePlanOnWeb(),
context: "local"
});
return;
}
eSendEvent(eCloseSheet);
if (!useUserStore.getState().user) {
Navigation.navigate("Auth", {
@@ -256,6 +259,7 @@ export default function PaywallSheet<Tid extends FeatureId>(props: {
}
PaywallSheet.present = <Tid extends FeatureId>(feature: FeatureResult<Tid>) => {
if (SettingsService.getProperty("serverUrls")) return;
presentSheet({
component: <PaywallSheet feature={feature} />
});

View File

@@ -20,6 +20,7 @@ import Paragraph from "../../ui/typography/paragraph";
import { SubscriptionPlan, SubscriptionProvider } from "@notesnook/core";
import { useUserStore } from "../../../stores/use-user-store";
import PremiumService from "../../../services/premium";
import SettingsService from "../../../services/settings";
export function PlanLimits() {
const { colors } = useThemeColors();
@@ -84,10 +85,11 @@ export function PlanLimits() {
</View>
))}
{(user?.subscription?.provider === SubscriptionProvider.PADDLE ||
{((user?.subscription?.provider === SubscriptionProvider.PADDLE ||
user?.subscription?.provider === SubscriptionProvider.STREETWRITERS ||
!isCurrentPlatform) &&
PremiumService.get() ? null : (
PremiumService.get()) ||
SettingsService.getProperty("serverUrls") ? null : (
<Button
title={strings.changePlan()}
onPress={() => {

View File

@@ -24,10 +24,11 @@ import { FlatList, View } from "react-native";
import { DraxProvider, DraxScrollView } from "react-native-drax";
import { db } from "../../common/database";
import Navigation from "../../services/navigation";
import SettingsService from "../../services/settings";
import { useMenuStore } from "../../stores/use-menu-store";
import { useSettingStore } from "../../stores/use-setting-store";
import { useUserStore } from "../../stores/use-user-store";
import { SUBSCRIPTION_STATUS } from "../../utils/constants";
import { MenuItemsList } from "../../utils/menu-items";
import { DefaultAppStyles } from "../../utils/styles";
import ReorderableList from "../list/reorderable-list";
import { MenuItemProperties } from "../sheets/menu-item-properties";
@@ -36,7 +37,6 @@ import { ColorSection } from "./color-section";
import { MenuItem } from "./menu-item";
import { PinnedSection } from "./pinned-section";
import { SideMenuHeader } from "./side-menu-header";
import { MenuItemsList } from "../../utils/menu-items";
const pro = {
title: strings.upgradePlan(),
@@ -140,9 +140,10 @@ export function SideMenuHome() {
paddingVertical: DefaultAppStyles.GAP_VERTICAL
}}
>
{subscriptionType === SubscriptionPlan.FREE ||
!subscriptionType ||
!user ? (
{(subscriptionType === SubscriptionPlan.FREE ||
!subscriptionType ||
!user) &&
!SettingsService.getProperty("serverUrls") ? (
<Button
title={pro.title}
style={{

View File

@@ -85,6 +85,7 @@ export default function useFeatureManager() {
negativeText: strings.cancel(),
positivePress: async () => {
eSendEvent(eCloseSimpleDialog);
if (SettingsService.getProperty("serverUrls")) return;
Navigation.navigate("PayWall", {
context: "logged-in"
});

View File

@@ -25,6 +25,7 @@ import { DatabaseLogger, db } from "../common/database";
import PremiumService from "../services/premium";
import { useSettingStore } from "../stores/use-setting-store";
import { useUserStore } from "../stores/use-user-store";
import SettingsService from "../services/settings";
function numberWithCommas(x: string) {
const parts = x.toString().split(".");
parts[0] = parts[0].replace(/\B(?=(\d{3})+(?!\d))/g, ",");
@@ -201,7 +202,7 @@ const usePricingPlans = (options?: PricingPlansOptions) => {
if (productId?.includes("5year")) return false;
if (isGithubRelease) {
if (
user?.subscription.trialsAvailed?.some(
user?.subscription?.trialsAvailed?.some(
(plan) => plan === planIdToIndex(planId || currentPlan)
)
) {
@@ -246,7 +247,10 @@ const usePricingPlans = (options?: PricingPlansOptions) => {
});
setPlans([...pricingPlans]);
setUserCanRequestTrial(hasTrialOffer());
if (Config.GITHUB_RELEASE === "true") {
if (
Config.GITHUB_RELEASE === "true" &&
!SettingsService.getProperty("serverUrls")
) {
try {
const products = WebPlanCache || (await db.pricing.products());
WebPlanCache = products;
@@ -264,7 +268,8 @@ const usePricingPlans = (options?: PricingPlansOptions) => {
if (!product) return;
if (Platform.OS === "android") {
if (isGithubRelease)
if (isGithubRelease) {
if (!(product as Plan)?.price) return null;
return `${(product as Plan).price.currency} ${
(product as Plan).period === "yearly"
? ((product as Plan).price.gross / 12).toFixed(2)
@@ -272,6 +277,7 @@ const usePricingPlans = (options?: PricingPlansOptions) => {
? ((product as Plan).price.gross / (12 * 5)).toFixed(2)
: (product as Plan).price.gross
}`;
}
const pricingPhaseListItem =
(product as RNIap.SubscriptionAndroid)?.subscriptionOfferDetails?.[0]
@@ -414,7 +420,7 @@ const usePricingPlans = (options?: PricingPlansOptions) => {
offerIndex: number
) => {
if (isGithubRelease) {
return (product as Plan).period;
return (product as Plan)?.period;
}
if (Platform.OS === "android") {
@@ -444,7 +450,7 @@ const usePricingPlans = (options?: PricingPlansOptions) => {
if (isGithubRelease) {
return {
duration: 1,
type: (product as Plan).period
type: (product as Plan)?.period
};
}
@@ -591,7 +597,8 @@ const usePricingPlans = (options?: PricingPlansOptions) => {
) => {
if (!product) return null;
if (isGithubRelease)
if (isGithubRelease) {
if (!(product as Plan)?.price) return null;
return `${(product as Plan).price.currency} ${
(product as Plan).period === "yearly"
? ((product as Plan).price.gross / 12).toFixed(2)
@@ -599,6 +606,7 @@ const usePricingPlans = (options?: PricingPlansOptions) => {
? ((product as Plan).price.gross / (12 * 5)).toFixed(2)
: (product as Plan).price.gross
}`;
}
const androidPricingPhase = (product as RNIap.SubscriptionAndroid)
?.subscriptionOfferDetails?.[0].pricingPhases?.pricingPhaseList?.[

View File

@@ -43,6 +43,7 @@ import { planToDisplayName } from "../../utils/constants";
import { AppFontSize } from "../../utils/size";
import { DefaultAppStyles } from "../../utils/styles";
import { SectionItem } from "./section-item";
import SettingsService from "../../services/settings";
export const getTimeLeft = (t2) => {
let daysRemaining = dayjs(t2).diff(dayjs(), "days");
@@ -339,11 +340,13 @@ const SettingsUserSection = ({ item }) => {
</Paragraph>
</TouchableOpacity>
{(user.subscription?.provider === SubscriptionProvider.PADDLE ||
{((user.subscription?.provider ===
SubscriptionProvider.PADDLE ||
user.subscription?.provider ===
SubscriptionProvider.STREETWRITERS ||
!isCurrentPlatform) &&
PremiumService.get() ? null : (
PremiumService.get()) ||
SettingsService.getProperty("serverUrls") ? null : (
<Button
title={
user.subscription?.plan !== SubscriptionPlan.FREE

View File

@@ -71,6 +71,7 @@ export function planToDisplayName(plan: SubscriptionPlan): string {
return strings.freePlan();
case SubscriptionPlan.ESSENTIAL:
return strings.essentialPlan();
case SubscriptionPlan.LEGACY_PRO:
case SubscriptionPlan.PRO:
return strings.proPlan();
case SubscriptionPlan.BELIEVER:

File diff suppressed because one or more lines are too long

View File

@@ -1,12 +1,12 @@
{
"name": "@notesnook/web",
"version": "3.3.0",
"version": "3.3.1",
"lockfileVersion": 3,
"requires": true,
"packages": {
"": {
"name": "@notesnook/web",
"version": "3.3.0",
"version": "3.3.1",
"hasInstallScript": true,
"license": "GPL-3.0-or-later",
"dependencies": {

View File

@@ -1,7 +1,7 @@
{
"name": "@notesnook/web",
"description": "Your private note taking space",
"version": "3.3.0",
"version": "3.3.1",
"private": true,
"main": "./src/app.js",
"homepage": "https://notesnook.com/",

View File

@@ -87,6 +87,8 @@ export async function scheduleFullBackups() {
}
export async function shouldAddAutoBackupsDisabledNotice() {
if (isIgnored("autoBackupsOff")) return false;
const user = await db.user.getUser();
if (!user) return false;

View File

@@ -50,7 +50,6 @@ const TRIAL_PERIODS: Record<Period, number> = {
};
export function toPricingInfo(plan: Plan, user: User | undefined): PricingInfo {
console.log("TO PRICING INFO", plan);
return {
country: plan.country,
period: plan.period,
@@ -58,9 +57,9 @@ export function toPricingInfo(plan: Plan, user: User | undefined): PricingInfo {
currency: plan.currency,
id: plan.id,
period: plan.period,
subtotal: formatPrice(plan.price.gross, plan.currency),
subtotal: formatPrice(plan.price.net, plan.currency),
tax: formatPrice(plan.price.tax, plan.currency),
total: formatPrice(plan.price.net, plan.currency),
total: formatPrice(plan.price.gross, plan.currency),
trial_period: isTrialAvailableForPlan(plan.plan, user)
? {
frequency: TRIAL_PERIODS[plan.period]
@@ -74,9 +73,9 @@ export function toPricingInfo(plan: Plan, user: User | undefined): PricingInfo {
currency: plan.currency,
id: plan.id,
period: plan.period,
subtotal: formatPrice(plan.price.gross, plan.currency),
subtotal: formatPrice(plan.price.net, plan.currency),
tax: formatPrice(plan.price.tax, plan.currency),
total: formatPrice(plan.price.net, plan.currency)
total: formatPrice(plan.price.gross, plan.currency)
}
: undefined
};

View File

@@ -245,7 +245,7 @@ function getPricingInfo(
id: price.price_id,
period: options.period,
subtotal: formatPrice(
data.recurring_totals.subtotal,
data.recurring_totals.subtotal - data.recurring_totals.discount,
data.currency_code
),
total: formatPrice(data.recurring_totals.total, data.currency_code),
@@ -256,7 +256,10 @@ function getPricingInfo(
currency: data.currency_code,
id: price.price_id,
period: options.period,
subtotal: formatPrice(totals.subtotal, data.currency_code),
subtotal: formatPrice(
totals.subtotal - totals.discount,
data.currency_code
),
total: formatPrice(totals.total, data.currency_code),
tax: formatPrice(totals.tax, data.currency_code),
trial_period: price.trial_period

View File

@@ -22,7 +22,7 @@ import { updateStatus } from "../hooks/use-status";
import {
Gateway,
WEB_EXTENSION_CHANNEL_EVENTS
} from "@notesnook/web-clipper/dist/common/bridge";
} from "@notesnook/web-clipper/common/bridge.js";
import { Extension } from "../components/icons";
export class WebExtensionRelay {

View File

@@ -23,7 +23,7 @@ import {
NotebookReference,
Server,
Clip
} from "@notesnook/web-clipper/dist/common/bridge";
} from "@notesnook/web-clipper/common/bridge.js";
import { store as appstore } from "../stores/app-store";
import { h } from "./html";
import { sanitizeFilename } from "@notesnook/common";

View File

@@ -119,7 +119,7 @@ function Checkout() {
useEffect(() => {
if (currentStep === 2) {
var event = EV.subscribe(EVENTS.userSubscriptionUpdated, () => {
const event = EV.subscribe(EVENTS.userSubscriptionUpdated, () => {
hardNavigate("/notes#/welcome");
});
return () => {

View File

@@ -2,7 +2,31 @@
"name": "@notesnook/web-clipper",
"version": "0.3.4",
"private": true,
"main": "./dist/index.js",
"main": "./dist/cjs/index.js",
"module": "./dist/esm/index.js",
"types": "./dist/types/index.d.ts",
"exports": {
".": {
"require": {
"types": "./dist/types/index.d.ts",
"default": "./dist/cjs/index.js"
},
"import": {
"types": "./dist/types/index.d.ts",
"default": "./dist/esm/index.js"
}
},
"./*": {
"require": {
"types": "./dist/types/*",
"default": "./dist/cjs/*"
},
"import": {
"types": "./dist/types/*",
"default": "./dist/esm/*"
}
}
},
"dependencies": {
"@emotion/react": "11.11.1",
"@mdi/js": "7.4.47",
@@ -28,7 +52,7 @@
"build:chrome": "cross-env MANIFEST_VERSION=3 node build-utils/build.js",
"dev:chrome": "cross-env MANIFEST_VERSION=3 node build-utils/dev.js",
"dev:firefox": "cross-env MANIFEST_VERSION=2 node build-utils/dev.js",
"build": "tsc"
"build": "node ../../scripts/build.mjs"
},
"browserslist": {
"production": [
@@ -94,4 +118,4 @@
},
"homepage": "https://notesnook.com/",
"repository": "https://github.com/streetwriters/notesnook"
}
}

View File

@@ -1,6 +0,0 @@
{
"$schema": "node_modules/lerna/schemas/lerna-schema.json",
"useNx": true,
"version": "independent",
"packages": ["packages/*", "apps/*", "extensions/*", "servers/*"]
}

76
nx.json
View File

@@ -1,76 +0,0 @@
{
"targetDefaults": {
"build": {
"dependsOn": ["^build"],
"outputs": [
"{projectRoot}/build",
"{projectRoot}/dist",
"{projectRoot}/languages",
"{projectRoot}/locales",
"{projectRoot}/src/extensions/code-block/languages"
],
"cache": true
},
"release": {
"dependsOn": ["^build"],
"outputs": ["{projectRoot}/build"]
},
"build:test": {
"dependsOn": ["^build"],
"outputs": ["{projectRoot}/build"],
"cache": true
},
"build:beta": {
"dependsOn": ["^build"],
"outputs": ["{projectRoot}/build"]
},
"build:desktop": {
"dependsOn": ["^build"],
"outputs": ["{projectRoot}/build"],
"cache": true
},
"start": {
"dependsOn": ["^build"]
},
"start:desktop": {
"dependsOn": ["^build"]
},
"test:e2e": {
"dependsOn": ["^build"]
},
"test": {
"dependsOn": ["^build"]
},
"run-android": {
"dependsOn": ["^build"]
},
"run-ios": {
"dependsOn": ["^build"]
},
"build-ios": {
"dependsOn": ["^build"]
},
"build-android": {
"dependsOn": ["^build"]
},
"release-android": {
"dependsOn": ["^build"]
},
"release-android-bundle": {
"dependsOn": ["^build"]
},
"release-ios": {
"dependsOn": ["^build"]
},
"repack": {
"dependsOn": ["^build"]
}
},
"namedInputs": {
"default": ["{projectRoot}/**/*", "sharedGlobals"],
"sharedGlobals": [],
"production": ["default"]
},
"parallel": 4,
"nxCloudAccessToken": "ZWM3ODgxNDgtNGUzZC00MjQ0LWE3MzMtZDdhMzE3ZGY2MWFlfHJlYWQ="
}

4682
package-lock.json generated

File diff suppressed because it is too large Load Diff

View File

@@ -5,46 +5,49 @@
"prepare": "husky install && npm run bootstrap",
"bootstrap": "node scripts/bootstrap.mjs",
"clean": "node scripts/clean.mjs",
"build": "nx run-many --target=build --all --exclude=@notesnook/mobile,@notesnook/web",
"build:web": "nx build @notesnook/web",
"build:vericrypt": "nx build @notesnook/vericrypt",
"build:test:web": "nx build:test @notesnook/web",
"build:beta:web": "nx build:beta @notesnook/web",
"start:web": "nx start @notesnook/web",
"start:theme-builder": "nx start @notesnook/theme-builder",
"build:theme-builder": "nx build @notesnook/theme-builder",
"start:vericrypt": "nx start @notesnook/vericrypt",
"start:desktop": "nx start @notesnook/desktop",
"test:web": "nx test @notesnook/web",
"test:core": "nx test @notesnook/core",
"start:android": "nx run-android @notesnook/mobile",
"start:ios": "nx run-ios @notesnook/mobile",
"prepare:ios": "nx install-pods @notesnook/mobile",
"build:ios": "nx build-ios @notesnook/mobile",
"build:android": "nx build-android @notesnook/mobile",
"build:android:debug": "nx build-android-debug @notesnook/mobile",
"release:android": "nx release-android @notesnook/mobile",
"release:android:bundle": "nx release-android-bundle @notesnook/mobile",
"test:ios": "nx e2e-ios @notesnook/mobile",
"test:android": "nx e2e-android @notesnook/mobile",
"test:android:debug": "nx e2e-android-debug @notesnook/mobile",
"start:metro": "nx start @notesnook/mobile",
"start:repack": "nx repack @notesnook/mobile",
"start:editor-mobile": "nx start @notesnook/editor-mobile",
"start:editor": "nx start @notesnook/editor",
"start:server:themes": "nx start @notesnook/themes-server",
"build:intl": "nx build @notesnook/intl",
"start:intl": "nx start @notesnook/intl",
"build": "npm run tx -- build --all --exclude=mobile,web,monograph,theme-builder,vericrypt",
"build:web": "npm run tx web:build",
"build:vericrypt": "npm run tx vericrypt:build",
"build:test:web": "npm run tx web:build:test",
"build:beta:web": "npm run tx web:build:beta",
"start:web": "npm run tx web:start",
"start:theme-builder": "npm run tx theme-builder:start",
"build:theme-builder": "npm run tx theme-builder:build",
"start:vericrypt": "npm run tx vericrypt:start",
"start:desktop": "npm run tx desktop:start",
"test:web": "npm run tx web:test",
"test:core": "npm run tx core:test",
"start:android": "npm run tx mobile:run-android",
"start:ios": "npm run tx mobile:run-ios",
"prepare:ios": "npm run tx mobile:install-pods",
"build:ios": "npm run tx mobile:build-ios",
"build:android": "npm run tx mobile:build-android",
"build:android:debug": "npm run tx mobile:build-android-debug",
"release:android": "npm run tx mobile:release-android",
"release:android:bundle": "npm run tx mobile:release-android-bundle",
"test:ios": "npm run tx mobile:e2e-ios",
"test:android": "npm run tx mobile:e2e-android",
"test:android:debug": "npm run tx mobile:e2e-android-debug",
"start:metro": "npm run tx mobile:start",
"start:repack": "npm run tx mobile:repack",
"start:editor-mobile": "npm run tx editor-mobile:start",
"start:editor": "npm run tx editor:start",
"start:server:themes": "npm run tx themes-server:start",
"build:intl": "npm run tx intl:build",
"start:intl": "npm run tx intl:start",
"prettier": "npx prettier . --write",
"lint": "npx eslint ./apps/ ./packages/",
"linc": "npx eslint ./apps/ ./packages/ --cache"
"linc": "npx eslint ./apps/ ./packages/ --cache",
"tx": "node scripts/execute.mjs"
},
"devDependencies": {
"@commitlint/cli": "^17.1.1",
"@types/node": "^18.7.13",
"@typescript-eslint/eslint-plugin": "^5.59.9",
"@typescript-eslint/parser": "^5.59.9",
"@typescript/native-preview": "^7.0.0-dev.20251006.1",
"cross-env": "^7.0.3",
"dotenv": "^17.2.3",
"eslint": "^8.42.0",
"eslint-config-react-app": "^7.0.1",
"eslint-config-react-hooks": "^1.0.0",
@@ -58,13 +61,13 @@
"husky": "^8.0.1",
"prettier": "^2.8.8",
"serve": "^14.0.1",
"tsdown": "^0.15.6",
"tsup": "^8.1.0"
},
"dependencies": {
"eslint-plugin-header": "^3.1.1",
"fdir": "^6.0.2",
"fdir": "^6.5.0",
"listr2": "^8.2.3",
"nx": "^21.6.3",
"patch-package": "^7.0.0",
"rxjs": "^7.8.1",
"typescript": "^5.6.3",
@@ -72,26 +75,42 @@
},
"license": "GPL-3.0-or-later",
"volta": {
"node": "20.12.0"
"node": "22.20.0"
},
"taskRunner": {
"projects": [
"packages/**",
"apps/**",
"extensions/**",
"servers/**"
"packages/*",
"apps/*",
"extensions/*",
"servers/*"
],
"taskDependencies": {
"build": [
"build"
],
"release": [
"build"
],
"build:desktop": [
"build"
]
}
"tasks": [
{
"dependencies": [
"build"
],
"commands": [
"start",
"build",
"release",
"build:test",
"build:beta",
"build:desktop",
"start",
"start:desktop",
"test:e2e",
"test",
"run-android",
"run-ios",
"build-ios",
"build-android",
"release-android",
"release-android-bundle",
"release-ios",
"repack"
]
}
]
},
"packageManager": "yarn@1.22.22+sha512.a6b2f7906b721bba3d67d4aff083df04dad64c399707841b7acf00f6b133b7ac24255f2652fa22ae3534329dc6180534e98d17432037ff6fd140556e2bb3137e"
}

File diff suppressed because it is too large Load Diff

View File

@@ -11,9 +11,8 @@
"main": "dist/index.js",
"devDependencies": {
"@playwright/test": "1.48.2",
"slugify": "1.6.6",
"webpack": "5.88.2",
"webpack-cli": "5.1.4"
"@rsbuild/core": "^1.5.13",
"slugify": "1.6.6"
},
"publishConfig": {
"access": "public"
@@ -23,7 +22,7 @@
"url": "git+https://github.com/streetwriters/notesnook.git"
},
"scripts": {
"build": "tsc && yarn webpack -c webpack.config.js",
"build": "tsc && npx rsbuild build",
"prepublishOnly": "npm run build",
"test": "playwright test",
"postinstall": "patch-package",
@@ -38,4 +37,4 @@
"hyperapp": "^2.0.22",
"specificity": "^0.4.1"
}
}
}

View File

@@ -17,15 +17,27 @@ You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
const path = require("path");
module.exports = {
entry: ["./dist/index.global.js"],
import { defineConfig } from "@rsbuild/core";
import path from "path";
export default defineConfig({
source: {
entry: {
global: "./dist/index.global.js"
}
},
mode: "production",
output: {
filename: "clipper.bundle.js",
path: path.resolve(
__dirname,
"../../apps/mobile/native/ios/extension.bundle"
)
target: "node",
cleanDistPath: false,
filename: {
js: "clipper.bundle.js"
},
distPath: {
root: path.resolve(
__dirname,
"../../apps/mobile/native/ios/extension.bundle"
)
}
}
};
});

View File

@@ -222,7 +222,7 @@ export const tiptapKeys = {
type: "tiptap"
},
insertParagraph: {
keys: "Mod-Shift-0",
keys: "Mod-Alt-0",
description: "Insert paragraph",
category: "Editor",
type: "tiptap"

View File

@@ -68,20 +68,23 @@ test("editing the same note should create multiple history sessions", () =>
test("restoring an old session should replace note's content", () =>
noteTest({ ...TEST_NOTE, sessionId: Date.now() }).then(async ({ db, id }) => {
await delay(1000);
let editedContent = {
data: TEST_NOTE.content.data + "<p>Some new content</p>",
type: "tiptap"
};
const sessionId = `${Date.now() + 10000}`;
await db.notes.add({
id: id,
content: editedContent,
sessionId: Date.now() + 10000
sessionId
});
const [, firstVersion] = await db.noteHistory
.get(id)
.items(undefined, { sortBy: "dateModified", sortDirection: "desc" });
expect(firstVersion.id).not.toBe(`${id}_${sessionId}`);
await db.noteHistory.restore(firstVersion.id);
const contentId = (await db.notes.note(id)).contentId;
@@ -138,15 +141,17 @@ test("return empty array if no history available", () =>
test("auto clear sessions if they exceed the limit", () =>
noteTest({ ...TEST_NOTE, sessionId: Date.now() }).then(async ({ db, id }) => {
await delay(1000);
let editedContent = {
data: TEST_NOTE.content.data + "<p>Some new content</p>",
type: "tiptap"
};
const sessionId = `${Date.now() + 10000}`;
await db.notes.add({
id: id,
content: editedContent,
sessionId: `${Date.now() + 10000}`
sessionId
});
expect(await db.noteHistory.get(id).count()).toBe(2);
@@ -157,6 +162,7 @@ test("auto clear sessions if they exceed the limit", () =>
expect(sessions).toHaveLength(1);
const content = await db.noteHistory.content(sessions[0].id);
expect(sessions[0].id).toBe(`${id}_${sessionId}`);
expect(content.data).toBe(editedContent.data);
}));

View File

@@ -18,7 +18,7 @@
}
},
"scripts": {
"build": "tsup-node src/index.ts",
"build": "tsdown src/index.ts",
"prepublishOnly": "npm run build",
"watch": "npm run build -- --watch"
},

View File

@@ -66,6 +66,7 @@
"devDependencies": {
"@emotion/react": "11.11.1",
"@mdi/js": "7.4.47",
"@rslib/core": "^0.15.0",
"@theme-ui/components": "0.16.1",
"@theme-ui/core": "0.16.1",
"@types/katex": "0.16.7",
@@ -77,6 +78,7 @@
"happy-dom": "16.0.1",
"isomorphic-fetch": "^3.0.0",
"nodemon": "^3.1.7",
"prismjs": "^1.30.0",
"prosemirror-test-builder": "^1.1.1",
"react": "18.3.1",
"react-dom": "18.3.1",
@@ -260,6 +262,180 @@
"react-modal": ">=3"
}
},
"node_modules/@ast-grep/napi": {
"version": "0.37.0",
"resolved": "https://registry.npmjs.org/@ast-grep/napi/-/napi-0.37.0.tgz",
"integrity": "sha512-Hb4o6h1Pf6yRUAX07DR4JVY7dmQw+RVQMW5/m55GoiAT/VRoKCWBtIUPPOnqDVhbx1Cjfil9b6EDrgJsUAujEQ==",
"dev": true,
"license": "MIT",
"engines": {
"node": ">= 10"
},
"optionalDependencies": {
"@ast-grep/napi-darwin-arm64": "0.37.0",
"@ast-grep/napi-darwin-x64": "0.37.0",
"@ast-grep/napi-linux-arm64-gnu": "0.37.0",
"@ast-grep/napi-linux-arm64-musl": "0.37.0",
"@ast-grep/napi-linux-x64-gnu": "0.37.0",
"@ast-grep/napi-linux-x64-musl": "0.37.0",
"@ast-grep/napi-win32-arm64-msvc": "0.37.0",
"@ast-grep/napi-win32-ia32-msvc": "0.37.0",
"@ast-grep/napi-win32-x64-msvc": "0.37.0"
}
},
"node_modules/@ast-grep/napi-darwin-arm64": {
"version": "0.37.0",
"resolved": "https://registry.npmjs.org/@ast-grep/napi-darwin-arm64/-/napi-darwin-arm64-0.37.0.tgz",
"integrity": "sha512-QAiIiaAbLvMEg/yBbyKn+p1gX2/FuaC0SMf7D7capm/oG4xGMzdeaQIcSosF4TCxxV+hIH4Bz9e4/u7w6Bnk3Q==",
"cpu": [
"arm64"
],
"dev": true,
"license": "MIT",
"optional": true,
"os": [
"darwin"
],
"engines": {
"node": ">= 10"
}
},
"node_modules/@ast-grep/napi-darwin-x64": {
"version": "0.37.0",
"resolved": "https://registry.npmjs.org/@ast-grep/napi-darwin-x64/-/napi-darwin-x64-0.37.0.tgz",
"integrity": "sha512-zvcvdgekd4ySV3zUbUp8HF5nk5zqwiMXTuVzTUdl/w08O7JjM6XPOIVT+d2o/MqwM9rsXdzdergY5oY2RdhSPA==",
"cpu": [
"x64"
],
"dev": true,
"license": "MIT",
"optional": true,
"os": [
"darwin"
],
"engines": {
"node": ">= 10"
}
},
"node_modules/@ast-grep/napi-linux-arm64-gnu": {
"version": "0.37.0",
"resolved": "https://registry.npmjs.org/@ast-grep/napi-linux-arm64-gnu/-/napi-linux-arm64-gnu-0.37.0.tgz",
"integrity": "sha512-L7Sj0lXy8X+BqSMgr1LB8cCoWk0rericdeu+dC8/c8zpsav5Oo2IQKY1PmiZ7H8IHoFBbURLf8iklY9wsD+cyA==",
"cpu": [
"arm64"
],
"dev": true,
"license": "MIT",
"optional": true,
"os": [
"linux"
],
"engines": {
"node": ">= 10"
}
},
"node_modules/@ast-grep/napi-linux-arm64-musl": {
"version": "0.37.0",
"resolved": "https://registry.npmjs.org/@ast-grep/napi-linux-arm64-musl/-/napi-linux-arm64-musl-0.37.0.tgz",
"integrity": "sha512-LF9sAvYy6es/OdyJDO3RwkX3I82Vkfsng1sqUBcoWC1jVb1wX5YVzHtpQox9JrEhGl+bNp7FYxB4Qba9OdA5GA==",
"cpu": [
"arm64"
],
"dev": true,
"license": "MIT",
"optional": true,
"os": [
"linux"
],
"engines": {
"node": ">= 10"
}
},
"node_modules/@ast-grep/napi-linux-x64-gnu": {
"version": "0.37.0",
"resolved": "https://registry.npmjs.org/@ast-grep/napi-linux-x64-gnu/-/napi-linux-x64-gnu-0.37.0.tgz",
"integrity": "sha512-TViz5/klqre6aSmJzswEIjApnGjJzstG/SE8VDWsrftMBMYt2PTu3MeluZVwzSqDao8doT/P+6U11dU05UOgxw==",
"cpu": [
"x64"
],
"dev": true,
"license": "MIT",
"optional": true,
"os": [
"linux"
],
"engines": {
"node": ">= 10"
}
},
"node_modules/@ast-grep/napi-linux-x64-musl": {
"version": "0.37.0",
"resolved": "https://registry.npmjs.org/@ast-grep/napi-linux-x64-musl/-/napi-linux-x64-musl-0.37.0.tgz",
"integrity": "sha512-/BcCH33S9E3ovOAEoxYngUNXgb+JLg991sdyiNP2bSoYd30a9RHrG7CYwW6fMgua3ijQ474eV6cq9yZO1bCpXg==",
"cpu": [
"x64"
],
"dev": true,
"license": "MIT",
"optional": true,
"os": [
"linux"
],
"engines": {
"node": ">= 10"
}
},
"node_modules/@ast-grep/napi-win32-arm64-msvc": {
"version": "0.37.0",
"resolved": "https://registry.npmjs.org/@ast-grep/napi-win32-arm64-msvc/-/napi-win32-arm64-msvc-0.37.0.tgz",
"integrity": "sha512-TjQA4cFoIEW2bgjLkaL9yqT4XWuuLa5MCNd0VCDhGRDMNQ9+rhwi9eLOWRaap3xzT7g+nlbcEHL3AkVCD2+b3A==",
"cpu": [
"arm64"
],
"dev": true,
"license": "MIT",
"optional": true,
"os": [
"win32"
],
"engines": {
"node": ">= 10"
}
},
"node_modules/@ast-grep/napi-win32-ia32-msvc": {
"version": "0.37.0",
"resolved": "https://registry.npmjs.org/@ast-grep/napi-win32-ia32-msvc/-/napi-win32-ia32-msvc-0.37.0.tgz",
"integrity": "sha512-uNmVka8fJCdYsyOlF9aZqQMLTatEYBynjChVTzUfFMDfmZ0bihs/YTqJVbkSm8TZM7CUX82apvn50z/dX5iWRA==",
"cpu": [
"ia32"
],
"dev": true,
"license": "MIT",
"optional": true,
"os": [
"win32"
],
"engines": {
"node": ">= 10"
}
},
"node_modules/@ast-grep/napi-win32-x64-msvc": {
"version": "0.37.0",
"resolved": "https://registry.npmjs.org/@ast-grep/napi-win32-x64-msvc/-/napi-win32-x64-msvc-0.37.0.tgz",
"integrity": "sha512-vCiFOT3hSCQuHHfZ933GAwnPzmL0G04JxQEsBRfqONywyT8bSdDc/ECpAfr3S9VcS4JZ9/F6tkePKW/Om2Dq2g==",
"cpu": [
"x64"
],
"dev": true,
"license": "MIT",
"optional": true,
"os": [
"win32"
],
"engines": {
"node": ">= 10"
}
},
"node_modules/@azure/msal-browser": {
"version": "3.28.1",
"resolved": "https://registry.npmjs.org/@azure/msal-browser/-/msal-browser-3.28.1.tgz",
@@ -489,6 +665,40 @@
"node": ">=6.9.0"
}
},
"node_modules/@emnapi/core": {
"version": "1.5.0",
"resolved": "https://registry.npmjs.org/@emnapi/core/-/core-1.5.0.tgz",
"integrity": "sha512-sbP8GzB1WDzacS8fgNPpHlp6C9VZe+SJP3F90W9rLemaQj2PzIuTEl1qDOYQf58YIpyjViI24y9aPWCjEzY2cg==",
"dev": true,
"license": "MIT",
"optional": true,
"dependencies": {
"@emnapi/wasi-threads": "1.1.0",
"tslib": "^2.4.0"
}
},
"node_modules/@emnapi/runtime": {
"version": "1.5.0",
"resolved": "https://registry.npmjs.org/@emnapi/runtime/-/runtime-1.5.0.tgz",
"integrity": "sha512-97/BJ3iXHww3djw6hYIfErCZFee7qCtrneuLa20UXFCOTCfBM2cvQHjWJ2EG0s0MtdNwInarqCTz35i4wWXHsQ==",
"dev": true,
"license": "MIT",
"optional": true,
"dependencies": {
"tslib": "^2.4.0"
}
},
"node_modules/@emnapi/wasi-threads": {
"version": "1.1.0",
"resolved": "https://registry.npmjs.org/@emnapi/wasi-threads/-/wasi-threads-1.1.0.tgz",
"integrity": "sha512-WI0DdZ8xFSbgMjR1sFsKABJ/C5OnRrjT06JXbZKexJGrDuPTzZdDYfFlsgcCXCyf+suG5QU2e/y1Wo2V/OapLQ==",
"dev": true,
"license": "MIT",
"optional": true,
"dependencies": {
"tslib": "^2.4.0"
}
},
"node_modules/@emotion/babel-plugin": {
"version": "11.12.0",
"resolved": "https://registry.npmjs.org/@emotion/babel-plugin/-/babel-plugin-11.12.0.tgz",
@@ -1074,6 +1284,78 @@
}
}
},
"node_modules/@module-federation/error-codes": {
"version": "0.18.0",
"resolved": "https://registry.npmjs.org/@module-federation/error-codes/-/error-codes-0.18.0.tgz",
"integrity": "sha512-Woonm8ehyVIUPXChmbu80Zj6uJkC0dD9SJUZ/wOPtO8iiz/m+dkrOugAuKgoiR6qH4F+yorWila954tBz4uKsQ==",
"dev": true,
"license": "MIT"
},
"node_modules/@module-federation/runtime": {
"version": "0.18.0",
"resolved": "https://registry.npmjs.org/@module-federation/runtime/-/runtime-0.18.0.tgz",
"integrity": "sha512-+C4YtoSztM7nHwNyZl6dQKGUVJdsPrUdaf3HIKReg/GQbrt9uvOlUWo2NXMZ8vDAnf/QRrpSYAwXHmWDn9Obaw==",
"dev": true,
"license": "MIT",
"dependencies": {
"@module-federation/error-codes": "0.18.0",
"@module-federation/runtime-core": "0.18.0",
"@module-federation/sdk": "0.18.0"
}
},
"node_modules/@module-federation/runtime-core": {
"version": "0.18.0",
"resolved": "https://registry.npmjs.org/@module-federation/runtime-core/-/runtime-core-0.18.0.tgz",
"integrity": "sha512-ZyYhrDyVAhUzriOsVfgL6vwd+5ebYm595Y13KeMf6TKDRoUHBMTLGQ8WM4TDj8JNsy7LigncK8C03fn97of0QQ==",
"dev": true,
"license": "MIT",
"dependencies": {
"@module-federation/error-codes": "0.18.0",
"@module-federation/sdk": "0.18.0"
}
},
"node_modules/@module-federation/runtime-tools": {
"version": "0.18.0",
"resolved": "https://registry.npmjs.org/@module-federation/runtime-tools/-/runtime-tools-0.18.0.tgz",
"integrity": "sha512-fSga9o4t1UfXNV/Kh6qFvRyZpPp3EHSPRISNeyT8ZoTpzDNiYzhtw0BPUSSD8m6C6XQh2s/11rI4g80UY+d+hA==",
"dev": true,
"license": "MIT",
"dependencies": {
"@module-federation/runtime": "0.18.0",
"@module-federation/webpack-bundler-runtime": "0.18.0"
}
},
"node_modules/@module-federation/sdk": {
"version": "0.18.0",
"resolved": "https://registry.npmjs.org/@module-federation/sdk/-/sdk-0.18.0.tgz",
"integrity": "sha512-Lo/Feq73tO2unjmpRfyyoUkTVoejhItXOk/h5C+4cistnHbTV8XHrW/13fD5e1Iu60heVdAhhelJd6F898Ve9A==",
"dev": true,
"license": "MIT"
},
"node_modules/@module-federation/webpack-bundler-runtime": {
"version": "0.18.0",
"resolved": "https://registry.npmjs.org/@module-federation/webpack-bundler-runtime/-/webpack-bundler-runtime-0.18.0.tgz",
"integrity": "sha512-TEvErbF+YQ+6IFimhUYKK3a5wapD90d90sLsNpcu2kB3QGT7t4nIluE25duXuZDVUKLz86tEPrza/oaaCWTpvQ==",
"dev": true,
"license": "MIT",
"dependencies": {
"@module-federation/runtime": "0.18.0",
"@module-federation/sdk": "0.18.0"
}
},
"node_modules/@napi-rs/wasm-runtime": {
"version": "1.0.6",
"resolved": "https://registry.npmjs.org/@napi-rs/wasm-runtime/-/wasm-runtime-1.0.6.tgz",
"integrity": "sha512-DXj75ewm11LIWUk198QSKUTxjyRjsBwk09MuMk5DGK+GDUtyPhhEHOGP/Xwwj3DjQXXkivoBirmOnKrLfc0+9g==",
"dev": true,
"license": "MIT",
"optional": true,
"dependencies": {
"@emnapi/core": "^1.5.0",
"@emnapi/runtime": "^1.5.0",
"@tybys/wasm-util": "^0.10.1"
}
},
"node_modules/@notesnook-importer/core": {
"version": "2.2.2",
"resolved": "https://registry.npmjs.org/@notesnook-importer/core/-/core-2.2.2.tgz",
@@ -1445,6 +1727,247 @@
"win32"
]
},
"node_modules/@rsbuild/core": {
"version": "1.5.13",
"resolved": "https://registry.npmjs.org/@rsbuild/core/-/core-1.5.13.tgz",
"integrity": "sha512-P+TCvZCVpBYZ3GDdnzR/tZKicE41khJIqIRlJYnEc9dwUfX1/eqRf8lA8yrsbB5iZbSfj1iOoH1N25cCQ3hhuA==",
"dev": true,
"license": "MIT",
"dependencies": {
"@rspack/core": "1.5.8",
"@rspack/lite-tapable": "~1.0.1",
"@swc/helpers": "^0.5.17",
"core-js": "~3.45.1",
"jiti": "^2.6.0"
},
"bin": {
"rsbuild": "bin/rsbuild.js"
},
"engines": {
"node": ">=18.12.0"
}
},
"node_modules/@rslib/core": {
"version": "0.15.0",
"resolved": "https://registry.npmjs.org/@rslib/core/-/core-0.15.0.tgz",
"integrity": "sha512-ZxDwEU38qsM32VpW4Dy7oNf6MxgrRAgYxVsuv8v+aKm4pIOSs0nzDTJHsa2vhKjFdyRtgnHObZ6pjoJ0cmcU3A==",
"dev": true,
"license": "MIT",
"dependencies": {
"@rsbuild/core": "~1.5.13",
"rsbuild-plugin-dts": "0.15.0"
},
"bin": {
"rslib": "bin/rslib.js"
},
"engines": {
"node": ">=18.12.0"
},
"peerDependencies": {
"@microsoft/api-extractor": "^7",
"typescript": "^5"
},
"peerDependenciesMeta": {
"@microsoft/api-extractor": {
"optional": true
},
"typescript": {
"optional": true
}
}
},
"node_modules/@rspack/binding": {
"version": "1.5.8",
"resolved": "https://registry.npmjs.org/@rspack/binding/-/binding-1.5.8.tgz",
"integrity": "sha512-/91CzhRl9r5BIQCgGsS7jA6MDbw1I2BQpbfcUUdkdKl2P79K3Zo/Mw/TvKzS86catwLaUQEgkGRmYawOfPg7ow==",
"dev": true,
"license": "MIT",
"optionalDependencies": {
"@rspack/binding-darwin-arm64": "1.5.8",
"@rspack/binding-darwin-x64": "1.5.8",
"@rspack/binding-linux-arm64-gnu": "1.5.8",
"@rspack/binding-linux-arm64-musl": "1.5.8",
"@rspack/binding-linux-x64-gnu": "1.5.8",
"@rspack/binding-linux-x64-musl": "1.5.8",
"@rspack/binding-wasm32-wasi": "1.5.8",
"@rspack/binding-win32-arm64-msvc": "1.5.8",
"@rspack/binding-win32-ia32-msvc": "1.5.8",
"@rspack/binding-win32-x64-msvc": "1.5.8"
}
},
"node_modules/@rspack/binding-darwin-arm64": {
"version": "1.5.8",
"resolved": "https://registry.npmjs.org/@rspack/binding-darwin-arm64/-/binding-darwin-arm64-1.5.8.tgz",
"integrity": "sha512-spJfpOSN3f7V90ic45/ET2NKB2ujAViCNmqb0iGurMNQtFRq+7Kd+jvVKKGXKBHBbsQrFhidSWbbqy2PBPGK8g==",
"cpu": [
"arm64"
],
"dev": true,
"license": "MIT",
"optional": true,
"os": [
"darwin"
]
},
"node_modules/@rspack/binding-darwin-x64": {
"version": "1.5.8",
"resolved": "https://registry.npmjs.org/@rspack/binding-darwin-x64/-/binding-darwin-x64-1.5.8.tgz",
"integrity": "sha512-YFOzeL1IBknBcri8vjUp43dfUBylCeQnD+9O9p0wZmLAw7DtpN5JEOe2AkGo8kdTqJjYKI+cczJPKIw6lu1LWw==",
"cpu": [
"x64"
],
"dev": true,
"license": "MIT",
"optional": true,
"os": [
"darwin"
]
},
"node_modules/@rspack/binding-linux-arm64-gnu": {
"version": "1.5.8",
"resolved": "https://registry.npmjs.org/@rspack/binding-linux-arm64-gnu/-/binding-linux-arm64-gnu-1.5.8.tgz",
"integrity": "sha512-UAWCsOnpkvy8eAVRo0uipbHXDhnoDq5zmqWTMhpga0/a3yzCp2e+fnjZb/qnFNYb5MeL0O1mwMOYgn1M3oHILQ==",
"cpu": [
"arm64"
],
"dev": true,
"license": "MIT",
"optional": true,
"os": [
"linux"
]
},
"node_modules/@rspack/binding-linux-arm64-musl": {
"version": "1.5.8",
"resolved": "https://registry.npmjs.org/@rspack/binding-linux-arm64-musl/-/binding-linux-arm64-musl-1.5.8.tgz",
"integrity": "sha512-GnSvGT4GjokPSD45cTtE+g7LgghuxSP1MRmvd+Vp/I8pnxTVSTsebRod4TAqyiv+l11nuS8yqNveK9qiOkBLWw==",
"cpu": [
"arm64"
],
"dev": true,
"license": "MIT",
"optional": true,
"os": [
"linux"
]
},
"node_modules/@rspack/binding-linux-x64-gnu": {
"version": "1.5.8",
"resolved": "https://registry.npmjs.org/@rspack/binding-linux-x64-gnu/-/binding-linux-x64-gnu-1.5.8.tgz",
"integrity": "sha512-XLxh5n/pzUfxsugz/8rVBv+Tx2nqEM+9rharK69kfooDsQNKyz7PANllBQ/v4svJ+W0BRHnDL4qXSGdteZeEjA==",
"cpu": [
"x64"
],
"dev": true,
"license": "MIT",
"optional": true,
"os": [
"linux"
]
},
"node_modules/@rspack/binding-linux-x64-musl": {
"version": "1.5.8",
"resolved": "https://registry.npmjs.org/@rspack/binding-linux-x64-musl/-/binding-linux-x64-musl-1.5.8.tgz",
"integrity": "sha512-gE0+MZmwF+01p9/svpEESkzkLpBkVUG2o03YMpwXYC/maeRRhWvF8BJ7R3i/Ls/jFGSE87dKX5NbRLVzqksq/w==",
"cpu": [
"x64"
],
"dev": true,
"license": "MIT",
"optional": true,
"os": [
"linux"
]
},
"node_modules/@rspack/binding-wasm32-wasi": {
"version": "1.5.8",
"resolved": "https://registry.npmjs.org/@rspack/binding-wasm32-wasi/-/binding-wasm32-wasi-1.5.8.tgz",
"integrity": "sha512-cfg3niNHeJuxuml1Vy9VvaJrI/5TakzoaZvKX2g5S24wfzR50Eyy4JAsZ+L2voWQQp1yMJbmPYPmnTCTxdJQBQ==",
"cpu": [
"wasm32"
],
"dev": true,
"license": "MIT",
"optional": true,
"dependencies": {
"@napi-rs/wasm-runtime": "^1.0.5"
}
},
"node_modules/@rspack/binding-win32-arm64-msvc": {
"version": "1.5.8",
"resolved": "https://registry.npmjs.org/@rspack/binding-win32-arm64-msvc/-/binding-win32-arm64-msvc-1.5.8.tgz",
"integrity": "sha512-7i3ZTHFXKfU/9Jm9XhpMkrdkxO7lfeYMNVEGkuU5dyBfRMQj69dRgPL7zJwc2plXiqu9LUOl+TwDNTjap7Q36g==",
"cpu": [
"arm64"
],
"dev": true,
"license": "MIT",
"optional": true,
"os": [
"win32"
]
},
"node_modules/@rspack/binding-win32-ia32-msvc": {
"version": "1.5.8",
"resolved": "https://registry.npmjs.org/@rspack/binding-win32-ia32-msvc/-/binding-win32-ia32-msvc-1.5.8.tgz",
"integrity": "sha512-7ZPPWO11J+soea1+mnfaPpQt7GIodBM7A86dx6PbXgVEoZmetcWPrCF2NBfXxQWOKJ9L3RYltC4z+ZyXRgMOrw==",
"cpu": [
"ia32"
],
"dev": true,
"license": "MIT",
"optional": true,
"os": [
"win32"
]
},
"node_modules/@rspack/binding-win32-x64-msvc": {
"version": "1.5.8",
"resolved": "https://registry.npmjs.org/@rspack/binding-win32-x64-msvc/-/binding-win32-x64-msvc-1.5.8.tgz",
"integrity": "sha512-N/zXQgzIxME3YUzXT8qnyzxjqcnXudWOeDh8CAG9zqTCnCiy16SFfQ/cQgEoLlD9geQntV6jx2GbDDI5kpDGMQ==",
"cpu": [
"x64"
],
"dev": true,
"license": "MIT",
"optional": true,
"os": [
"win32"
]
},
"node_modules/@rspack/core": {
"version": "1.5.8",
"resolved": "https://registry.npmjs.org/@rspack/core/-/core-1.5.8.tgz",
"integrity": "sha512-sUd2LfiDhqYVfvknuoz0+/c+wSpn693xotnG5g1CSWKZArbtwiYzBIVnNlcHGmuoBRsnj/TkSq8dTQ7gwfBroQ==",
"dev": true,
"license": "MIT",
"dependencies": {
"@module-federation/runtime-tools": "0.18.0",
"@rspack/binding": "1.5.8",
"@rspack/lite-tapable": "1.0.1"
},
"engines": {
"node": ">=18.12.0"
},
"peerDependencies": {
"@swc/helpers": ">=0.5.1"
},
"peerDependenciesMeta": {
"@swc/helpers": {
"optional": true
}
}
},
"node_modules/@rspack/lite-tapable": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/@rspack/lite-tapable/-/lite-tapable-1.0.1.tgz",
"integrity": "sha512-VynGOEsVw2s8TAlLf/uESfrgfrq2+rcXB1muPJYBWbsm1Oa6r5qVQhjA5ggM6z/coYPrsVMgovl3Ff7Q7OCp1w==",
"dev": true,
"license": "MIT",
"engines": {
"node": ">=16.0.0"
}
},
"node_modules/@social-embed/lib": {
"version": "0.1.0-next.7",
"resolved": "https://registry.npmjs.org/@social-embed/lib/-/lib-0.1.0-next.7.tgz",
@@ -1755,6 +2278,49 @@
"@styled-system/css": "^5.1.5"
}
},
"node_modules/@swc/helpers": {
"version": "0.5.17",
"resolved": "https://registry.npmjs.org/@swc/helpers/-/helpers-0.5.17.tgz",
"integrity": "sha512-5IKx/Y13RsYd+sauPb2x+U/xZikHjolzfuDgTAl/Tdf3Q8rslRvC19NKDLgAJQ6wsqADk10ntlv08nPFw/gO/A==",
"dev": true,
"license": "Apache-2.0",
"dependencies": {
"tslib": "^2.8.0"
}
},
"node_modules/@theme-ui/color-modes": {
"version": "0.16.2",
"resolved": "https://registry.npmjs.org/@theme-ui/color-modes/-/color-modes-0.16.2.tgz",
"integrity": "sha512-jWEWx53lxNgWCT38i/kwLV2rsvJz8lVZgi5oImnVwYba9VejXD23q1ckbNFJHosQ8KKXY87ht0KPC6BQFIiHtQ==",
"dev": true,
"license": "MIT",
"peer": true,
"dependencies": {
"@theme-ui/core": "^0.16.2",
"@theme-ui/css": "^0.16.2",
"deepmerge": "^4.2.2"
},
"peerDependencies": {
"@emotion/react": "^11.11.1",
"react": ">=18"
}
},
"node_modules/@theme-ui/color-modes/node_modules/@theme-ui/core": {
"version": "0.16.2",
"resolved": "https://registry.npmjs.org/@theme-ui/core/-/core-0.16.2.tgz",
"integrity": "sha512-bBd/ltbwO9vIUjF1jtlOX6XN0IIOdf1vzBp2JCKsSOqdfn84m+XL8OogIe/zOhQ+aM94Nrq4+32tFJc8sFav4Q==",
"dev": true,
"license": "MIT",
"peer": true,
"dependencies": {
"@theme-ui/css": "^0.16.2",
"deepmerge": "^4.2.2"
},
"peerDependencies": {
"@emotion/react": "^11.11.1",
"react": ">=18"
}
},
"node_modules/@theme-ui/components": {
"version": "0.16.1",
"resolved": "https://registry.npmjs.org/@theme-ui/components/-/components-0.16.1.tgz",
@@ -1800,6 +2366,39 @@
"@emotion/react": "^11.11.1"
}
},
"node_modules/@theme-ui/theme-provider": {
"version": "0.16.2",
"resolved": "https://registry.npmjs.org/@theme-ui/theme-provider/-/theme-provider-0.16.2.tgz",
"integrity": "sha512-LRnVevODcGqO0JyLJ3wht+PV3ZoZcJ7XXLJAJWDoGeII4vZcPQKwVy4Lpz/juHsZppQxKcB3U+sQDGBnP25irQ==",
"dev": true,
"license": "MIT",
"peer": true,
"dependencies": {
"@theme-ui/color-modes": "^0.16.2",
"@theme-ui/core": "^0.16.2",
"@theme-ui/css": "^0.16.2"
},
"peerDependencies": {
"@emotion/react": "^11.11.1",
"react": ">=18"
}
},
"node_modules/@theme-ui/theme-provider/node_modules/@theme-ui/core": {
"version": "0.16.2",
"resolved": "https://registry.npmjs.org/@theme-ui/core/-/core-0.16.2.tgz",
"integrity": "sha512-bBd/ltbwO9vIUjF1jtlOX6XN0IIOdf1vzBp2JCKsSOqdfn84m+XL8OogIe/zOhQ+aM94Nrq4+32tFJc8sFav4Q==",
"dev": true,
"license": "MIT",
"peer": true,
"dependencies": {
"@theme-ui/css": "^0.16.2",
"deepmerge": "^4.2.2"
},
"peerDependencies": {
"@emotion/react": "^11.11.1",
"react": ">=18"
}
},
"node_modules/@tiptap/core": {
"version": "2.6.6",
"resolved": "https://registry.npmjs.org/@tiptap/core/-/core-2.6.6.tgz",
@@ -2291,6 +2890,17 @@
"@tiptap/core": "^2.6.6"
}
},
"node_modules/@tybys/wasm-util": {
"version": "0.10.1",
"resolved": "https://registry.npmjs.org/@tybys/wasm-util/-/wasm-util-0.10.1.tgz",
"integrity": "sha512-9tTaPJLSiejZKx+Bmog4uSubteqTvFrVrURwkmHixBo0G4seD0zUxp98E1DzUBJxLQ3NPwXrGKDiVjwx/DpPsg==",
"dev": true,
"license": "MIT",
"optional": true,
"dependencies": {
"tslib": "^2.4.0"
}
},
"node_modules/@types/debug": {
"version": "4.1.12",
"resolved": "https://registry.npmjs.org/@types/debug/-/debug-4.1.12.tgz",
@@ -2922,6 +3532,18 @@
"integrity": "sha512-ASFBup0Mz1uyiIjANan1jzLQami9z1PoYSZCiiYW2FczPbenXc45FZdBZLzOT+r6+iciuEModtmCti+hjaAk0A==",
"dev": true
},
"node_modules/core-js": {
"version": "3.45.1",
"resolved": "https://registry.npmjs.org/core-js/-/core-js-3.45.1.tgz",
"integrity": "sha512-L4NPsJlCfZsPeXukyzHFlg/i7IIVwHSItR0wg0FLNqYClJ4MQYTYLbC7EkjKYRLZF2iof2MUgN0EGy7MdQFChg==",
"dev": true,
"hasInstallScript": true,
"license": "MIT",
"funding": {
"type": "opencollective",
"url": "https://opencollective.com/core-js"
}
},
"node_modules/cosmiconfig": {
"version": "7.1.0",
"resolved": "https://registry.npmjs.org/cosmiconfig/-/cosmiconfig-7.1.0.tgz",
@@ -3154,6 +3776,17 @@
"safe-buffer": "^5.0.1"
}
},
"node_modules/encoding": {
"version": "0.1.13",
"resolved": "https://registry.npmjs.org/encoding/-/encoding-0.1.13.tgz",
"integrity": "sha512-ETBauow1T35Y/WZMkio9jiM0Z5xjHHmJ4XmjZOq1l/dXz3lr2sRn87nJy20RupqSh1F2m3HHPSp8ShIPQJrJ3A==",
"license": "MIT",
"optional": true,
"peer": true,
"dependencies": {
"iconv-lite": "^0.6.2"
}
},
"node_modules/end-of-stream": {
"version": "1.4.4",
"resolved": "https://registry.npmjs.org/end-of-stream/-/end-of-stream-1.4.4.tgz",
@@ -3638,6 +4271,20 @@
"url": "https://github.com/fb55/entities?sponsor=1"
}
},
"node_modules/iconv-lite": {
"version": "0.6.3",
"resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.6.3.tgz",
"integrity": "sha512-4fCk79wshMdzMp2rH06qWrJE4iolqLhCUH+OiuIgU++RB0+94NlDL81atO7GX55uUKueo0txHNtvEyI6D7WdMw==",
"license": "MIT",
"optional": true,
"peer": true,
"dependencies": {
"safer-buffer": ">= 2.1.2 < 3.0.0"
},
"engines": {
"node": ">=0.10.0"
}
},
"node_modules/ieee754": {
"version": "1.2.1",
"resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.2.1.tgz",
@@ -3865,11 +4512,20 @@
"whatwg-fetch": "^3.4.1"
}
},
"node_modules/jiti": {
"version": "2.6.1",
"resolved": "https://registry.npmjs.org/jiti/-/jiti-2.6.1.tgz",
"integrity": "sha512-ekilCSN1jwRvIbgeg/57YFh8qQDNbwDb9xT/qu2DAHbFFZUicIl4ygVaAvzveMhMVr3LnpSKTNnwt8PoOfmKhQ==",
"dev": true,
"license": "MIT",
"bin": {
"jiti": "lib/jiti-cli.mjs"
}
},
"node_modules/js-tokens": {
"version": "4.0.0",
"resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz",
"integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==",
"dev": true
"integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ=="
},
"node_modules/js-yaml": {
"version": "3.14.1",
@@ -4085,7 +4741,6 @@
"version": "1.4.0",
"resolved": "https://registry.npmjs.org/loose-envify/-/loose-envify-1.4.0.tgz",
"integrity": "sha512-lyuxPGr/Wfhrlem2CL/UcnUc1zcqKAImBDzukY7Y5F/yQiNdko6+fRLevlw1HgMySw7f611UIY408EtxRSoK3Q==",
"dev": true,
"dependencies": {
"js-tokens": "^3.0.0 || ^4.0.0"
},
@@ -5437,6 +6092,16 @@
"resolved": "https://registry.npmjs.org/prism-themes/-/prism-themes-1.9.0.tgz",
"integrity": "sha512-tX2AYsehKDw1EORwBps+WhBFKc2kxfoFpQAjxBndbZKr4fRmMkv47XN0BghC/K1qwodB1otbe4oF23vUTFDokw=="
},
"node_modules/prismjs": {
"version": "1.30.0",
"resolved": "https://registry.npmjs.org/prismjs/-/prismjs-1.30.0.tgz",
"integrity": "sha512-DEvV2ZF2r2/63V+tK8hQvrR2ZGn10srHbXviTlcv7Kpzw8jWiNTqbVgjO3IY8RxrrOUF8VPMQQFysYYYv0YZxw==",
"dev": true,
"license": "MIT",
"engines": {
"node": ">=6"
}
},
"node_modules/prop-types": {
"version": "15.8.1",
"resolved": "https://registry.npmjs.org/prop-types/-/prop-types-15.8.1.tgz",
@@ -5708,7 +6373,6 @@
"version": "18.3.1",
"resolved": "https://registry.npmjs.org/react/-/react-18.3.1.tgz",
"integrity": "sha512-wS+hAgJShR0KhEvPJArfuPVN1+Hz1t0Y6n5jLrGQbkb4urgPE/0Rve+1kMB1v/oWgHgm4WIcV+i7F2pTVj+2iQ==",
"dev": true,
"dependencies": {
"loose-envify": "^1.1.0"
},
@@ -5729,7 +6393,6 @@
"version": "18.3.1",
"resolved": "https://registry.npmjs.org/react-dom/-/react-dom-18.3.1.tgz",
"integrity": "sha512-5m4nQKp+rZRb09LNH59GM4BxTh9251/ylbKIbpe7TpGxfJ+9kv6BLkLBXIjjspbgbnIBNqlI23tRnTWT0snUIw==",
"dev": true,
"dependencies": {
"loose-envify": "^1.1.0",
"scheduler": "^0.23.2"
@@ -6042,6 +6705,36 @@
"resolved": "https://registry.npmjs.org/rope-sequence/-/rope-sequence-1.3.4.tgz",
"integrity": "sha512-UT5EDe2cu2E/6O4igUr5PSFs23nvvukicWHx6GnOPlHAiiYbzNuCRQCuiUdHJQcqKalLKlrYJnjY0ySGsXNQXQ=="
},
"node_modules/rsbuild-plugin-dts": {
"version": "0.15.0",
"resolved": "https://registry.npmjs.org/rsbuild-plugin-dts/-/rsbuild-plugin-dts-0.15.0.tgz",
"integrity": "sha512-qKGCtv4fxKxWZb3DxHpgmP6uY+JAckovBE/92APerORvrtEtqwY6sAEY2UOaRo2ErENOiWhf5yFLE5EhdUsj9A==",
"dev": true,
"license": "MIT",
"dependencies": {
"@ast-grep/napi": "0.37.0"
},
"engines": {
"node": ">=18.12.0"
},
"peerDependencies": {
"@microsoft/api-extractor": "^7",
"@rsbuild/core": "1.x",
"@typescript/native-preview": "7.x",
"typescript": "^5"
},
"peerDependenciesMeta": {
"@microsoft/api-extractor": {
"optional": true
},
"@typescript/native-preview": {
"optional": true
},
"typescript": {
"optional": true
}
}
},
"node_modules/sade": {
"version": "1.8.1",
"resolved": "https://registry.npmjs.org/sade/-/sade-1.8.1.tgz",
@@ -6083,7 +6776,6 @@
"version": "0.23.2",
"resolved": "https://registry.npmjs.org/scheduler/-/scheduler-0.23.2.tgz",
"integrity": "sha512-UOShsPwz7NrMUqhR6t0hWjFduvOzbtv7toDH1/hIrfRNIDBnnBWd0CwJTGvTpngVlmwGCdP9/Zl/tVrDqcuYzQ==",
"dev": true,
"dependencies": {
"loose-envify": "^1.1.0"
}
@@ -6480,9 +7172,10 @@
}
},
"node_modules/tslib": {
"version": "2.6.2",
"resolved": "https://registry.npmjs.org/tslib/-/tslib-2.6.2.tgz",
"integrity": "sha512-AEYxH93jGFPn/a2iVAwW87VuUIkR1FVUKB77NwMF7nBTDkDrrT/Hpt/IrCJ0QXhW27jTBDcf5ZY7w6RiqTMw2Q=="
"version": "2.8.1",
"resolved": "https://registry.npmjs.org/tslib/-/tslib-2.8.1.tgz",
"integrity": "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==",
"license": "0BSD"
},
"node_modules/tunnel-agent": {
"version": "0.6.0",

View File

@@ -97,6 +97,7 @@
"happy-dom": "16.0.1",
"isomorphic-fetch": "^3.0.0",
"nodemon": "^3.1.7",
"prismjs": "^1.30.0",
"prosemirror-test-builder": "^1.1.1",
"react": "18.3.1",
"react-dom": "18.3.1",

View File

@@ -23,15 +23,16 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
import fs from "fs";
import { readFile } from "fs/promises";
import path from "path";
export async function langen(rootDirectory) {
const response = await fetch(
"https://github.com/PrismJS/prism/raw/master/components.json"
const json = JSON.parse(
await readFile(
path.join(rootDirectory, "node_modules", "prismjs", "components.json"),
"utf-8"
)
);
if (!response.ok) return {};
const json = await response.json();
let languages = [];
for (const key in json.languages) {
if (key === "meta") continue;

View File

@@ -42,7 +42,7 @@ export class ClipboardDOMParser extends ProsemirrorDOMParser {
convertGoogleDocsChecklist(dom);
formatCodeblocks(dom);
convertBrToSingleSpacedParagraphs(dom);
removeImages(dom);
removePremiumFeatures(dom);
removeBlockId(dom);
}
return super.parseSlice(dom, options);
@@ -53,7 +53,7 @@ export class ClipboardDOMParser extends ProsemirrorDOMParser {
convertGoogleDocsChecklist(dom);
formatCodeblocks(dom);
convertBrToSingleSpacedParagraphs(dom);
removeImages(dom);
removePremiumFeatures(dom);
removeBlockId(dom);
}
return super.parse(dom, options);
@@ -154,11 +154,29 @@ export function convertGoogleDocsChecklist(dom: HTMLElement | Document) {
}
}
export function removeImages(dom: HTMLElement | Document) {
let canInsertImages: boolean | null = null;
for (const img of dom.querySelectorAll(`img`)) {
canInsertImages = canInsertImages ?? hasPermission("insertImage");
if (!canInsertImages) img.remove();
const premiumFeatures = [
{
selector: "div.callout",
permission: "setCallout"
},
{
selector: 'ul[data-type="outlineList"]',
permission: "toggleOutlineList"
},
{
selector: "ul.checklist",
permission: "toggleTaskList"
}
] as const;
function removePremiumFeatures(dom: HTMLElement | Document) {
for (const feature of premiumFeatures) {
const elements = dom.querySelectorAll(feature.selector);
if (elements.length === 0) continue;
if (!hasPermission(feature.permission)) {
elements.forEach((element) => element.remove());
}
}
}

View File

@@ -69,10 +69,7 @@ export function TableComponent(props: ReactNodeViewProps) {
/>
</DesktopOnly>
<SimpleBar autoHide>
<Box
dir={textDirection}
sx={{ "& table": { width: "100% !important" } }}
>
<Box dir={textDirection}>
<table
ref={(ref) => {
forwardRef?.(ref);

View File

@@ -28,6 +28,7 @@ import {
import { useMemo } from "react";
import { CodeBlock } from "../../extensions/code-block/index.js";
import { strings } from "@notesnook/intl";
import { keybindings } from "@notesnook/common";
const defaultLevels = [1, 2, 3, 4, 5, 6] as const;
@@ -70,7 +71,7 @@ function toMenuItems(
key: `heading-${level}`,
title: toolbarLocation === "bottom" ? `H${level}` : strings.heading(level),
isChecked: level === currentHeadingLevel,
modifier: `Mod-Alt-${level}`,
modifier: keybindings[`insertHeading${level}`].keys,
onClick: () =>
editor
?.chain()
@@ -84,7 +85,7 @@ function toMenuItems(
type: "button",
title: strings.paragraph(),
isChecked: !currentHeadingLevel,
modifier: `Mod-Alt-0`,
modifier: keybindings.insertParagraph.keys,
onClick: () => editor.chain().focus().setParagraph().run()
};
return [paragraph, ...menuItems];

View File

@@ -3795,8 +3795,8 @@ msgstr "Member since {date}"
msgid "Merge cells"
msgstr "Merge cells"
#. placeholder {0}: progress ? `${progress?.collection}` : null
#. placeholder {1}: progress ? `(${progress.current}/${progress.total}) ` : null
#. placeholder {0}: progress ? `${progress?.collection}` : ""
#. placeholder {1}: progress ? `(${progress.current}/${progress.total}) ` : ""
#: src/strings.ts:246
msgid "Migrating {0} {1}... please wait"
msgstr "Migrating {0} {1}... please wait"

View File

@@ -3775,8 +3775,8 @@ msgstr ""
msgid "Merge cells"
msgstr ""
#. placeholder {0}: progress ? `${progress?.collection}` : null
#. placeholder {1}: progress ? `(${progress.current}/${progress.total}) ` : null
#. placeholder {0}: progress ? `${progress?.collection}` : ""
#. placeholder {1}: progress ? `(${progress.current}/${progress.total}) ` : ""
#: src/strings.ts:246
msgid "Migrating {0} {1}... please wait"
msgstr ""

View File

@@ -243,8 +243,8 @@ export const strings = {
collection: string;
current: number;
}) =>
t`Migrating ${progress ? `${progress?.collection}` : null} ${
progress ? `(${progress.current}/${progress.total}) ` : null
t`Migrating ${progress ? `${progress?.collection}` : ""} ${
progress ? `(${progress.current}/${progress.total}) ` : ""
}... please wait`,
migrationError: () =>
t`An error occurred while migrating your data. You can logout of your account and try to relogin. However this is not recommended as it may result in some data loss if your data was not synced.`,
@@ -1791,7 +1791,7 @@ For example:
],
shareWithFriendsDesc: () => t`Because where's the fun in nookin' alone?`,
notebooksAllCaps: () => t`NOTEBOOKS`,
authenticatedAs: (email?: string) => t`Authenticated as ${email}`,
authenticatedAs: (email: string) => t`Authenticated as ${email}`,
rememberedYourPassword: () => t`Remembered your password?`,
chooseRecoveryMethod: () => t`Choose a recovery method`,
chooseRecoveryMethodDesc: () => t`How do you want to recover your account?`,

View File

@@ -0,0 +1,58 @@
// vite.config.mts
import path, { resolve } from "path";
import { defineConfig } from "file:///Users/thecodrr/Sources/Repos/notesnook/packages/intl/node_modules/vite/dist/node/index.js";
import swc from "file:///Users/thecodrr/Sources/Repos/notesnook/packages/intl/node_modules/vite-plugin-swc-transform/dist/esm/index.js";
import dts from "file:///Users/thecodrr/Sources/Repos/notesnook/packages/intl/node_modules/vite-plugin-dts/dist/index.mjs";
import { fileURLToPath } from "url";
var __vite_injected_original_import_meta_url = "file:///Users/thecodrr/Sources/Repos/notesnook/packages/intl/vite.config.mts";
var __filename = fileURLToPath(__vite_injected_original_import_meta_url);
var __dirname = path.dirname(__filename);
var vite_config_default = defineConfig({
plugins: [
swc({
swcOptions: {
sourceMaps: true,
jsc: {
parser: {
syntax: "typescript",
tsx: true
},
baseUrl: __dirname,
paths: {
"$src/*": ["src/*"]
},
experimental: {
plugins: [
[
"@lingui/swc-plugin",
{
runtimeModules: {
i18n: ["$src/setup", "i18n"]
}
}
]
]
}
}
}
}),
dts({
exclude: ["**/locales/*.json"],
rollupTypes: true
})
],
build: {
lib: {
entry: resolve(__dirname, "src/index.ts"),
formats: ["cjs", "es"],
fileName(format) {
return format === "cjs" ? "index.js" : "index.mjs";
}
},
outDir: resolve(__dirname, "dist")
}
});
export {
vite_config_default as default
};
//# sourceMappingURL=data:application/json;base64,ewogICJ2ZXJzaW9uIjogMywKICAic291cmNlcyI6IFsidml0ZS5jb25maWcubXRzIl0sCiAgInNvdXJjZXNDb250ZW50IjogWyJjb25zdCBfX3ZpdGVfaW5qZWN0ZWRfb3JpZ2luYWxfZGlybmFtZSA9IFwiL1VzZXJzL3RoZWNvZHJyL1NvdXJjZXMvUmVwb3Mvbm90ZXNub29rL3BhY2thZ2VzL2ludGxcIjtjb25zdCBfX3ZpdGVfaW5qZWN0ZWRfb3JpZ2luYWxfZmlsZW5hbWUgPSBcIi9Vc2Vycy90aGVjb2Ryci9Tb3VyY2VzL1JlcG9zL25vdGVzbm9vay9wYWNrYWdlcy9pbnRsL3ZpdGUuY29uZmlnLm10c1wiO2NvbnN0IF9fdml0ZV9pbmplY3RlZF9vcmlnaW5hbF9pbXBvcnRfbWV0YV91cmwgPSBcImZpbGU6Ly8vVXNlcnMvdGhlY29kcnIvU291cmNlcy9SZXBvcy9ub3Rlc25vb2svcGFja2FnZXMvaW50bC92aXRlLmNvbmZpZy5tdHNcIjsvKlxuVGhpcyBmaWxlIGlzIHBhcnQgb2YgdGhlIE5vdGVzbm9vayBwcm9qZWN0IChodHRwczovL25vdGVzbm9vay5jb20vKVxuXG5Db3B5cmlnaHQgKEMpIDIwMjMgU3RyZWV0d3JpdGVycyAoUHJpdmF0ZSkgTGltaXRlZFxuXG5UaGlzIHByb2dyYW0gaXMgZnJlZSBzb2Z0d2FyZTogeW91IGNhbiByZWRpc3RyaWJ1dGUgaXQgYW5kL29yIG1vZGlmeVxuaXQgdW5kZXIgdGhlIHRlcm1zIG9mIHRoZSBHTlUgR2VuZXJhbCBQdWJsaWMgTGljZW5zZSBhcyBwdWJsaXNoZWQgYnlcbnRoZSBGcmVlIFNvZnR3YXJlIEZvdW5kYXRpb24sIGVpdGhlciB2ZXJzaW9uIDMgb2YgdGhlIExpY2Vuc2UsIG9yXG4oYXQgeW91ciBvcHRpb24pIGFueSBsYXRlciB2ZXJzaW9uLlxuXG5UaGlzIHByb2dyYW0gaXMgZGlzdHJpYnV0ZWQgaW4gdGhlIGhvcGUgdGhhdCBpdCB3aWxsIGJlIHVzZWZ1bCxcbmJ1dCBXSVRIT1VUIEFOWSBXQVJSQU5UWTsgd2l0aG91dCBldmVuIHRoZSBpbXBsaWVkIHdhcnJhbnR5IG9mXG5NRVJDSEFOVEFCSUxJVFkgb3IgRklUTkVTUyBGT1IgQSBQQVJUSUNVTEFSIFBVUlBPU0UuICBTZWUgdGhlXG5HTlUgR2VuZXJhbCBQdWJsaWMgTGljZW5zZSBmb3IgbW9yZSBkZXRhaWxzLlxuXG5Zb3Ugc2hvdWxkIGhhdmUgcmVjZWl2ZWQgYSBjb3B5IG9mIHRoZSBHTlUgR2VuZXJhbCBQdWJsaWMgTGljZW5zZVxuYWxvbmcgd2l0aCB0aGlzIHByb2dyYW0uICBJZiBub3QsIHNlZSA8aHR0cDovL3d3dy5nbnUub3JnL2xpY2Vuc2VzLz4uXG4qL1xuXG5pbXBvcnQgcGF0aCwgeyByZXNvbHZlIH0gZnJvbSBcInBhdGhcIjtcbmltcG9ydCB7IGRlZmluZUNvbmZpZyB9IGZyb20gXCJ2aXRlXCI7XG5pbXBvcnQgc3djIGZyb20gXCJ2aXRlLXBsdWdpbi1zd2MtdHJhbnNmb3JtXCI7XG5pbXBvcnQgZHRzIGZyb20gXCJ2aXRlLXBsdWdpbi1kdHNcIjtcbmltcG9ydCB7IGZpbGVVUkxUb1BhdGggfSBmcm9tIFwidXJsXCI7XG5cbmNvbnN0IF9fZmlsZW5hbWUgPSBmaWxlVVJMVG9QYXRoKGltcG9ydC5tZXRhLnVybCk7XG5jb25zdCBfX2Rpcm5hbWUgPSBwYXRoLmRpcm5hbWUoX19maWxlbmFtZSk7XG5cbmV4cG9ydCBkZWZhdWx0IGRlZmluZUNvbmZpZyh7XG4gIHBsdWdpbnM6IFtcbiAgICBzd2Moe1xuICAgICAgc3djT3B0aW9uczoge1xuICAgICAgICBzb3VyY2VNYXBzOiB0cnVlLFxuICAgICAgICBqc2M6IHtcbiAgICAgICAgICBwYXJzZXI6IHtcbiAgICAgICAgICAgIHN5bnRheDogXCJ0eXBlc2NyaXB0XCIsXG4gICAgICAgICAgICB0c3g6IHRydWVcbiAgICAgICAgICB9LFxuICAgICAgICAgIGJhc2VVcmw6IF9fZGlybmFtZSxcbiAgICAgICAgICBwYXRoczoge1xuICAgICAgICAgICAgXCIkc3JjLypcIjogW1wic3JjLypcIl1cbiAgICAgICAgICB9LFxuICAgICAgICAgIGV4cGVyaW1lbnRhbDoge1xuICAgICAgICAgICAgcGx1Z2luczogW1xuICAgICAgICAgICAgICBbXG4gICAgICAgICAgICAgICAgXCJAbGluZ3VpL3N3Yy1wbHVnaW5cIixcbiAgICAgICAgICAgICAgICB7XG4gICAgICAgICAgICAgICAgICBydW50aW1lTW9kdWxlczoge1xuICAgICAgICAgICAgICAgICAgICBpMThuOiBbXCIkc3JjL3NldHVwXCIsIFwiaTE4blwiXVxuICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgXVxuICAgICAgICAgICAgXVxuICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgfVxuICAgIH0pLFxuICAgIGR0cyh7XG4gICAgICBleGNsdWRlOiBbXCIqKi9sb2NhbGVzLyouanNvblwiXSxcbiAgICAgIHJvbGx1cFR5cGVzOiB0cnVlXG4gICAgfSlcbiAgXSxcbiAgYnVpbGQ6IHtcbiAgICBsaWI6IHtcbiAgICAgIGVudHJ5OiByZXNvbHZlKF9fZGlybmFtZSwgXCJzcmMvaW5kZXgudHNcIiksXG4gICAgICBmb3JtYXRzOiBbXCJjanNcIiwgXCJlc1wiXSxcbiAgICAgIGZpbGVOYW1lKGZvcm1hdCkge1xuICAgICAgICByZXR1cm4gZm9ybWF0ID09PSBcImNqc1wiID8gXCJpbmRleC5qc1wiIDogXCJpbmRleC5tanNcIjtcbiAgICAgIH1cbiAgICB9LFxuICAgIG91dERpcjogcmVzb2x2ZShfX2Rpcm5hbWUsIFwiZGlzdFwiKVxuICB9XG59KTtcbiJdLAogICJtYXBwaW5ncyI6ICI7QUFtQkEsT0FBTyxRQUFRLGVBQWU7QUFDOUIsU0FBUyxvQkFBb0I7QUFDN0IsT0FBTyxTQUFTO0FBQ2hCLE9BQU8sU0FBUztBQUNoQixTQUFTLHFCQUFxQjtBQXZCcUwsSUFBTSwyQ0FBMkM7QUF5QnBRLElBQU0sYUFBYSxjQUFjLHdDQUFlO0FBQ2hELElBQU0sWUFBWSxLQUFLLFFBQVEsVUFBVTtBQUV6QyxJQUFPLHNCQUFRLGFBQWE7QUFBQSxFQUMxQixTQUFTO0FBQUEsSUFDUCxJQUFJO0FBQUEsTUFDRixZQUFZO0FBQUEsUUFDVixZQUFZO0FBQUEsUUFDWixLQUFLO0FBQUEsVUFDSCxRQUFRO0FBQUEsWUFDTixRQUFRO0FBQUEsWUFDUixLQUFLO0FBQUEsVUFDUDtBQUFBLFVBQ0EsU0FBUztBQUFBLFVBQ1QsT0FBTztBQUFBLFlBQ0wsVUFBVSxDQUFDLE9BQU87QUFBQSxVQUNwQjtBQUFBLFVBQ0EsY0FBYztBQUFBLFlBQ1osU0FBUztBQUFBLGNBQ1A7QUFBQSxnQkFDRTtBQUFBLGdCQUNBO0FBQUEsa0JBQ0UsZ0JBQWdCO0FBQUEsb0JBQ2QsTUFBTSxDQUFDLGNBQWMsTUFBTTtBQUFBLGtCQUM3QjtBQUFBLGdCQUNGO0FBQUEsY0FDRjtBQUFBLFlBQ0Y7QUFBQSxVQUNGO0FBQUEsUUFDRjtBQUFBLE1BQ0Y7QUFBQSxJQUNGLENBQUM7QUFBQSxJQUNELElBQUk7QUFBQSxNQUNGLFNBQVMsQ0FBQyxtQkFBbUI7QUFBQSxNQUM3QixhQUFhO0FBQUEsSUFDZixDQUFDO0FBQUEsRUFDSDtBQUFBLEVBQ0EsT0FBTztBQUFBLElBQ0wsS0FBSztBQUFBLE1BQ0gsT0FBTyxRQUFRLFdBQVcsY0FBYztBQUFBLE1BQ3hDLFNBQVMsQ0FBQyxPQUFPLElBQUk7QUFBQSxNQUNyQixTQUFTLFFBQVE7QUFDZixlQUFPLFdBQVcsUUFBUSxhQUFhO0FBQUEsTUFDekM7QUFBQSxJQUNGO0FBQUEsSUFDQSxRQUFRLFFBQVEsV0FBVyxNQUFNO0FBQUEsRUFDbkM7QUFDRixDQUFDOyIsCiAgIm5hbWVzIjogW10KfQo=

View File

@@ -16,7 +16,7 @@
}
},
"scripts": {
"build": "tsup-node src/index.ts",
"build": "tsdown src/index.ts",
"prepublishOnly": "npm run build",
"watch": "npm run build -- --watch"
},

View File

@@ -36,7 +36,7 @@
"postbuild": "node scripts/postbuild.mjs",
"prepublishOnly": "npm run build && npm run test",
"postinstall": "patch-package",
"build": "tsup-node src/browser.ts src/node.ts",
"build": "tsdown src/browser.ts src/node.ts",
"watch": "npm run build -- --watch"
},
"license": "GPL-3.0-or-later",

View File

@@ -16,7 +16,7 @@
}
},
"scripts": {
"build": "tsup-node src/index.ts",
"build": "tsdown src/index.ts",
"prepublishOnly": "npm run build",
"watch": "npm run build -- --watch"
},

View File

@@ -20,6 +20,7 @@ import "isomorphic-fetch";
import { mkdir, writeFile } from "fs/promises";
import path from "path";
import { fileURLToPath } from "url";
import { existsSync } from "fs";
const __filename = fileURLToPath(import.meta.url);
const __dirname = path.dirname(__filename);
@@ -36,6 +37,8 @@ async function main() {
await mkdir(THEMES_DIRECTORY, { recursive: true });
for (const themeId of DEFAULT_THEMES) {
const themePath = path.join(THEMES_DIRECTORY, `${themeId}.json`);
if (existsSync(themePath)) continue;
console.log("Getting", themeId);
const BASE_URL = `https://raw.githubusercontent.com/streetwriters/notesnook-themes/main/themes/${themeId}/v${THEME_COMPATIBILITY_VERSION}`;

View File

@@ -46,8 +46,8 @@
"react-dom": ">=18"
},
"scripts": {
"build": "tsup-node src/index.ts",
"build": "tsdown src/index.ts",
"prepublishOnly": "npm run build",
"watch": "npm run build -- --watch"
}
}
}

View File

@@ -30,6 +30,11 @@ const TSC =
? path.join(__dirname, "..", "node_modules", ".bin", "tsc.cmd")
: path.join(__dirname, "..", "node_modules", ".bin", "tsc");
const TSCGO =
process.platform === "win32"
? path.join(__dirname, "..", "node_modules", ".bin", "tsgo.cmd")
: path.join(__dirname, "..", "node_modules", ".bin", "tsgo");
const esmPackageJson = {
type: "module"
};
@@ -62,7 +67,7 @@ await Promise.all([
IS_WATCH ? "--watch" : ""
),
cmd(
TSC,
TSCGO,
"--emitDeclarationOnly",
"--outDir",
"dist/types",
@@ -78,9 +83,10 @@ await Promise.all([
)
]);
function cmd(...command) {
async function cmd(...command) {
let p = spawn(command[0], command.slice(1), { shell: true });
return new Promise((resolveFunc) => {
console.time(command.join(" "));
await new Promise((resolveFunc) => {
p.stdout.on("data", (x) => {
process.stdout.write(x.toString());
});
@@ -88,8 +94,9 @@ function cmd(...command) {
process.stderr.write(x.toString());
});
p.on("exit", (code) => {
console.log(command.join(" "), "exited with code", code);
// console.log(command.join(" "), "exited with code", code);
resolveFunc(code);
});
});
console.timeEnd(command.join(" "));
}

View File

@@ -18,189 +18,352 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
import { spawn } from "child_process";
import { fdir } from "fdir";
import { existsSync, readFileSync, writeFileSync } from "fs";
import { readFile } from "fs/promises";
import { existsSync, readFileSync } from "fs";
import { glob, readFile, rename, stat, writeFile } from "fs/promises";
import path from "path";
import { fileURLToPath } from "url";
import parser from "yargs-parser";
import { performance } from "perf_hooks";
import { createHash } from "crypto";
const args = parser(process.argv, {
alias: { force: ["-f"], verbose: ["-v"] }
});
const isVerbose = process.env.CI || args.verbose;
const __filename = fileURLToPath(import.meta.url);
const __dirname = path.dirname(__filename);
const config = JSON.parse(
readFileSync(path.join(__dirname, "..", "package.json"), "utf-8")
).taskRunner;
const cache = JSON.parse(
existsSync(path.join(__dirname, "..", ".taskcache"))
? readFileSync(path.join(__dirname, "..", ".taskcache"), "utf-8")
: "{}"
);
let [project, ...taskParts] = process.argv.slice(2)[0].split(":");
const task = taskParts.join(":");
const allPackages = (
await new fdir()
.onlyDirs()
.withMaxDepth(2)
.glob(...config.projects)
.crawl(".")
.withPromise()
).slice(4);
for (const pkg of allPackages) {
if (isPackage(pkg, project)) {
project = pkg;
break;
const args = { _: [], exclude: [], force: false, verbose: false, all: false };
const shortFlags = { f: "force", v: "verbose", a: "all", e: "exclude" };
for (let i = 2; i < process.argv.length; i++) {
const arg = process.argv[i];
if (!arg.startsWith("-")) args._.push(arg);
else {
const isLong = arg.startsWith("--");
const [key, value] = isLong ? arg.split("=") : [arg[1], null];
const flag = isLong ? key.slice(2) : shortFlags[key];
if (!args[flag]) args._.push(arg);
else if (Array.isArray(args[flag]))
args[flag] = value
? value.split(",")
: process.argv[++i]?.split(",") || [];
else if (flag) args[flag] = true;
}
}
const pipeline = await buildExecutionPipeline(
config.taskDependencies[task],
project
);
console.log("Found", pipeline.length, "dependencies to run.");
for (const item of pipeline) {
const checksum = await computeDirectoryChecksum(item.dep);
if (checksum === cache[item.dep + ":" + item.cmd]) continue;
await runScript(item.cmd, item.dep);
cache[item.dep + ":" + item.cmd] = checksum;
if (!args._.length) {
console.error("Missing required argument: package:task");
process.exit(1);
}
await runScript(task, project);
const __dirname = path.dirname(fileURLToPath(import.meta.url));
const root = path.join(__dirname, "..");
const isVerbose = !!(process.env.CI || args.verbose);
const rootPkg = readJson(path.join(root, "package.json"));
const config = rootPkg.taskRunner || { projects: ["packages/*"], tasks: [] };
const cachePath = path.join(root, ".taskcache");
const [project, ...taskParts] = args.all
? [null, ...args._[0].split(":")]
: args._[0].split(":");
const cmd = taskParts.join(":");
const pkgCache = new Map();
const depMemo = new Map();
writeFileSync(
path.join(__dirname, "..", ".taskcache"),
JSON.stringify(cache, null, 2)
);
async function runScript(command, pkg) {
console.log(`Running "${command}" for ${pkg}`);
return new Promise((resolve, reject) => {
const child = spawn("npm", ["run", command], {
cwd: pkg,
stdio: isVerbose ? "inherit" : "pipe",
shell: true
});
child.on("exit", (code) => {
if (code === 0) {
resolve();
} else {
reject(new Error(`Command failed with exit code ${code}`));
}
});
child.on("error", (err) => {
reject(err);
});
});
const allPkgs = await findPkgs();
const task = config.tasks?.find((t) => t.commands?.includes(cmd));
if (!task) {
console.error(`Task "${cmd}" not found in taskRunner config.`);
process.exit(1);
}
async function buildExecutionPipeline(commands, pkg) {
if (commands.length === 0) return [];
const resolvedPkgs = (
await Promise.all(
task.dependencies.flatMap((dep) =>
allPkgs.map((pkg) => resolvePkg(dep, pkg))
)
)
).filter(Boolean);
const executionPipeline = [];
const deps = await findDependencies(pkg);
for (const dep of deps) {
if (executionPipeline.some((item) => item.dep === dep)) continue;
const pipeline = await buildExecutionPipeline(commands, dep);
for (const item of pipeline) {
if (executionPipeline.some((i) => i.dep === item.dep)) continue;
executionPipeline.push(item);
}
const json = JSON.parse(
readFileSync(path.join(dep, "package.json"), "utf-8")
);
for (const cmd of commands) {
if (json.scripts && json.scripts[cmd]) {
executionPipeline.push({
cmd,
dep
});
break;
}
}
}
return executionPipeline;
let cache = {};
try {
cache = existsSync(cachePath) ? readJson(cachePath) : {};
} catch {
if (isVerbose) console.warn("Failed to parse .taskcache");
}
function isPackage(pkg, name) {
const json = JSON.parse(
readFileSync(path.join(pkg, "package.json"), "utf-8")
);
return json.name === name;
}
async function findDependencies(scope) {
function readPkg(pkgPath) {
const key = path.resolve(pkgPath);
if (pkgCache.has(key)) return pkgCache.get(key);
try {
const packageJsonPath = path.join(scope, "package.json");
const packageJson = JSON.parse(await readFile(packageJsonPath, "utf-8"));
const json = readJson(path.join(pkgPath, "package.json"));
pkgCache.set(key, json);
return json;
} catch {
return null;
}
}
const dependencies = new Set([
...filterDependencies(scope, packageJson.dependencies),
...filterDependencies(scope, packageJson.devDependencies),
...filterDependencies(scope, packageJson.optionalDependencies),
...filterDependencies(scope, packageJson.peerDependencies)
]);
function readJson(jsonPath) {
return JSON.parse(readFileSync(jsonPath, "utf-8"));
}
for (const dependency of dependencies) {
(await findDependencies(dependency)).forEach((v) => dependencies.add(v));
}
function getPkgName(pkgPath) {
return readPkg(pkgPath)?.name || path.basename(pkgPath);
}
return Array.from(dependencies.values());
} catch (e) {
console.error("Failed to find dependencies for", scope, "Error:", e);
function isPkg(path, name) {
const pkgName = getPkgName(path);
return pkgName === name || pkgName.endsWith(`/${name}`);
}
async function findPkgs() {
const pkgs = [];
for await (const entry of glob(config.projects)) {
const pkgPath = path.join(root, entry);
if (existsSync(path.join(pkgPath, "package.json")))
pkgs.push(path.resolve(pkgPath));
}
return pkgs;
}
function filterDeps(base, deps) {
if (!deps) return [];
let filteredDeps = [];
for (const [key, value] of Object.entries(deps))
if (key.startsWith("@notesnook/") && value?.startsWith("file:"))
filteredDeps.push(path.resolve(base, value.slice(5)));
return filteredDeps;
}
async function findDeps(scope) {
const key = path.resolve(scope);
if (depMemo.has(key)) return depMemo.get(key);
const pkg = readPkg(scope);
if (!pkg) {
depMemo.set(key, []);
return [];
}
const deps = new Set(
filterDeps(scope, { ...pkg.dependencies, ...pkg.devDependencies })
);
for (const d of deps) for (const c of await findDeps(d)) deps.add(c);
const result = Array.from(deps);
depMemo.set(key, result);
return result;
}
function filterDependencies(basePath, dependencies) {
if (!dependencies) return [];
return Object.entries(dependencies)
.filter(
([key, value]) =>
key.startsWith("@notesnook/") || value.startsWith("file:")
)
.map(([_, value]) =>
path.resolve(path.join(basePath, value.replace("file:", "")))
);
}
async function computeDirectoryChecksum(dir) {
const exclusions = [
"node_modules",
".git",
"dist",
"build",
"out",
"locales",
"coverage"
];
const crypto = await import("crypto");
const hash = crypto.createHash("sha256");
const files = (
await new fdir()
.withFullPaths()
.exclude((dir) => exclusions.some((ex) => dir.includes(ex)))
.crawl(path.join(dir))
.withPromise()
).sort();
for (const filePath of files) {
const fileBuffer = await readFile(filePath);
hash.update(fileBuffer);
async function resolvePkg(command, pkgPath) {
const json = readPkg(pkgPath);
if (!json?.scripts?.[command]) return null;
const deps = await findDeps(pkgPath);
const taskDeps = {};
for (const dep of deps) {
if (readPkg(dep)?.scripts?.[command]) {
taskDeps[command] = taskDeps[command] || [];
taskDeps[command].push(dep);
}
}
return { path: pkgPath, cmd: command, taskDependencies: taskDeps };
}
async function runScript(command, pkg, opts) {
opts = opts || {};
const start = performance.now();
const name = getPkgName(pkg);
try {
await new Promise((resolve, reject) => {
const verbose = opts.verbose || isVerbose;
const child = spawn("npm", ["run", command, ...(opts.args || [])], {
cwd: pkg,
stdio: verbose ? "inherit" : "pipe",
shell: true
});
let output = "";
if (!verbose && child.stdout) {
child.stdout.on("data", (data) => (output += data));
child.stderr.on("data", (data) => (output += data));
}
child.once("exit", (code) =>
code === 0
? resolve()
: reject(new Error(`Exit code ${code}${output ? "\n" + output : ""}`))
);
child.once("error", reject);
});
console.log(
`${name}:${command} took ${(performance.now() - start).toFixed(0)}ms`
);
} catch (err) {
console.error(`${name}:${command} failed:`, err.message);
throw err;
}
}
function normalizePath(pathStr) {
return path.resolve(pathStr).replace(/\/$/, "");
}
async function toBatches(pkgs, cmd) {
const batches = [pkgs.filter((pkg) => !pkg.taskDependencies[cmd]?.length)];
const remaining = pkgs
.filter((pkg) => !!pkg.taskDependencies[cmd]?.length)
.slice();
while (remaining.length > 0) {
const batch = [];
for (const pkg of remaining.slice()) {
if (
pkg.taskDependencies[cmd].every((dep) =>
batches.some((batch) =>
batch.some(
(batchPkg) => normalizePath(dep) === normalizePath(batchPkg.path)
)
)
)
) {
batch.push(pkg);
remaining.splice(remaining.indexOf(pkg), 1);
}
}
if (!batch.length) throw new Error("Cyclic dependencies detected");
batches.push(batch);
}
return batches;
}
async function resolveRecursive(cmd, pkg, visited) {
visited = visited || new Set();
const result = [];
const resolved = await resolvePkg(cmd, pkg);
if (!resolved) return [];
const rp = path.resolve(pkg);
if (visited.has(rp)) return [];
visited.add(rp);
for (const dep of resolved.taskDependencies[cmd] || []) {
for (const resolved of await resolveRecursive(cmd, dep, visited)) {
if (!result.some((pkg) => pkg.path === resolved.path))
result.push(resolved);
}
}
result.push(resolved);
return result;
}
const exclusions = new Set([
"node_modules",
".git",
"dist",
"build",
"out",
"locales",
"coverage",
"__e2e__",
"__mocks__",
"__tests__",
"__benches__",
"scripts",
"test-artifacts",
"output"
]);
async function computeChecksumFast(dir) {
const hash = createHash("sha256");
for await (const entry of glob(`${dir}/**/**`, {
withFileTypes: true,
exclude: (entry) => exclusions.has(entry.name)
})) {
if (entry.isFile()) {
const fullPath = path.join(entry.parentPath, entry.name);
const fileStat = await stat(fullPath).catch(() => null);
if (!fileStat) continue;
hash.update(fullPath);
hash.update(fileStat.mtimeMs.toString());
hash.update(fileStat.size.toString());
}
}
return hash.digest("hex");
}
async function computeChecksumSlow(dir) {
const hash = createHash("sha256");
const files = [];
for await (const entry of glob(`${dir}/**/**`, {
withFileTypes: true,
exclude: (entry) => exclusions.has(entry.name)
})) {
if (entry.isFile()) files.push(path.join(entry.parentPath, entry.name));
}
files.sort();
for (const file of files) {
hash.update(path.relative(dir, file));
hash.update(await readFile(file).catch(() => ""));
}
return hash.digest("hex");
}
function findKeyInObject(obj, key) {
if (!obj || typeof obj !== "object" || Array.isArray(obj)) return;
if (key in obj) return obj[key];
for (const value of Object.values(obj)) {
const found = findKeyInObject(value, key);
if (found) return found;
}
}
function getBuildFolder(pkgPath) {
const pkg = readPkg(pkgPath);
if (!pkg) return null;
let artifact =
pkg.main ||
pkg.module ||
pkg.types ||
pkg.typings ||
findKeyInObject(pkg.exports, "default") ||
findKeyInObject(pkg.exports, "types");
if (!artifact) return null;
const dir = path.join(pkgPath, artifact.replace(/^\.\//, "").split("/")[0]);
return existsSync(dir) ? dir : null;
}
if (args.all) {
console.time("Took");
for (const dep of task.dependencies) {
for (const batch of await toBatches(resolvedPkgs, dep)) {
await Promise.all(
batch
.filter((pkg) => !args.exclude.some((name) => isPkg(pkg.path, name)))
.map((task) => runScript(task.cmd, task.path))
);
}
}
console.timeEnd("Took");
} else {
console.time("Ready in");
const pkg = resolvedPkgs.find((candidate) => isPkg(candidate.path, project));
if (!pkg) {
console.error(`Package "${project}" not found.`);
process.exit(1);
}
for (const dep of task.dependencies) {
for (const batch of await toBatches(
await resolveRecursive(dep, pkg.path),
dep
)) {
await Promise.all(
batch.map(async (item) => {
if (item.path === pkg.path) return;
const hasBuild = !!getBuildFolder(item.path);
const key = item.path + ":" + item.cmd;
const [fast, slow] = cache[key]?.split("|") || [];
const fastHash = await computeChecksumFast(item.path);
if (hasBuild && !args.force && fast === fastHash) return;
const slowHash = await computeChecksumSlow(item.path);
if (hasBuild && !args.force && slow === slowHash) return;
await runScript(item.cmd, item.path);
cache[key] = `${fastHash}|${slowHash}`;
})
);
}
}
const tmp = cachePath + ".tmp";
await writeFile(tmp, JSON.stringify(cache));
await rename(tmp, cachePath);
console.timeEnd("Ready in");
await runScript(cmd, pkg.path, {
verbose: true,
args: ["--", ...args._.slice(1)]
});
}

View File

@@ -3,6 +3,7 @@
"target": "es2016",
"module": "ESNext",
"moduleResolution": "node",
"incremental": true,
"esModuleInterop": true,
"forceConsistentCasingInFileNames": true,
"strict": true,

View File

@@ -17,12 +17,11 @@ You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
import { defineConfig } from "tsup";
import { defineConfig } from "tsdown";
export default defineConfig({
clean: true,
cjsInterop: true,
dts: true,
splitting: false,
format: ["cjs", "esm"]
format: ["cjs", "esm"],
dts: {
tsgo: true
}
});