@upstart.gg/vite-plugins 0.1.60 → 0.1.62
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/page-meta.js +533 -0
- package/dist/page-meta.js.map +1 -0
- package/dist/site-meta.d.ts +28 -0
- package/dist/site-meta.d.ts.map +1 -0
- package/dist/site-meta.js +207 -0
- package/dist/site-meta.js.map +1 -0
- package/dist/upstart-editor-api.d.ts +135 -1
- package/dist/upstart-editor-api.d.ts.map +1 -1
- package/dist/upstart-editor-api.js +756 -1
- package/dist/upstart-editor-api.js.map +1 -1
- package/dist/vite-plugin-upstart-attrs.d.ts.map +1 -1
- package/dist/vite-plugin-upstart-attrs.js +130 -10
- package/dist/vite-plugin-upstart-attrs.js.map +1 -1
- package/dist/vite-plugin-upstart-editor/runtime/index.d.ts.map +1 -1
- package/dist/vite-plugin-upstart-editor/runtime/index.js +35 -0
- package/dist/vite-plugin-upstart-editor/runtime/index.js.map +1 -1
- package/dist/vite-plugin-upstart-editor/runtime/text-editor.d.ts.map +1 -1
- package/dist/vite-plugin-upstart-editor/runtime/text-editor.js +139 -14
- package/dist/vite-plugin-upstart-editor/runtime/text-editor.js.map +1 -1
- package/dist/vite-plugin-upstart-editor/runtime/types.d.ts +3 -0
- package/dist/vite-plugin-upstart-editor/runtime/types.d.ts.map +1 -1
- package/package.json +8 -3
- package/src/page-meta.ts +678 -0
- package/src/site-meta.ts +226 -0
- package/src/tests/site-meta.test.ts +158 -0
- package/src/tests/upstart-editor-api-page-meta.test.ts +635 -0
- package/src/tests/vite-plugin-upstart-attrs.test.ts +224 -13
- package/src/upstart-editor-api.ts +941 -0
- package/src/vite-plugin-upstart-attrs.ts +253 -14
- package/src/vite-plugin-upstart-editor/runtime/index.ts +38 -0
- package/src/vite-plugin-upstart-editor/runtime/text-editor.ts +141 -14
- package/src/vite-plugin-upstart-editor/runtime/types.ts +2 -0
|
@@ -1701,7 +1701,7 @@ describe("upstart-editor-vite-plugin", () => {
|
|
|
1701
1701
|
expect(result).toContain('data-upstart-editable-text="true"');
|
|
1702
1702
|
});
|
|
1703
1703
|
|
|
1704
|
-
test("should
|
|
1704
|
+
test("should be editable with a prefix when Trans is mixed with static text", () => {
|
|
1705
1705
|
const code = `
|
|
1706
1706
|
import { Trans } from "react-i18next";
|
|
1707
1707
|
export default function App() {
|
|
@@ -1709,10 +1709,11 @@ describe("upstart-editor-vite-plugin", () => {
|
|
|
1709
1709
|
}
|
|
1710
1710
|
`;
|
|
1711
1711
|
const result = transform(code);
|
|
1712
|
-
// "Prefix: "
|
|
1713
|
-
//
|
|
1714
|
-
expect(result).
|
|
1715
|
-
expect(result).
|
|
1712
|
+
// "Prefix: " only surrounds a single i18n node → exported as a static affix so
|
|
1713
|
+
// the runtime editor keeps it out of the saved translation value
|
|
1714
|
+
expect(result).toContain('data-upstart-editable-text="true"');
|
|
1715
|
+
expect(result).toContain('data-upstart-i18n="translation:key"');
|
|
1716
|
+
expect(result).toContain('data-upstart-i18n-prefix="Prefix: "');
|
|
1716
1717
|
});
|
|
1717
1718
|
|
|
1718
1719
|
test("should promote <Trans> from inside && expression to parent", () => {
|
|
@@ -1735,8 +1736,8 @@ describe("upstart-editor-vite-plugin", () => {
|
|
|
1735
1736
|
}
|
|
1736
1737
|
`;
|
|
1737
1738
|
const result = transform(code);
|
|
1738
|
-
//
|
|
1739
|
-
expect(result).toContain('data-upstart-i18n="app:welcome
|
|
1739
|
+
// Only one branch renders, so the key is resolved at runtime from the condition
|
|
1740
|
+
expect(result).toContain('data-upstart-i18n={isLoggedIn ? "app:welcome" : "app:login"}');
|
|
1740
1741
|
expect(result).toContain('data-upstart-editable-text="true"');
|
|
1741
1742
|
});
|
|
1742
1743
|
|
|
@@ -1842,9 +1843,11 @@ describe("upstart-editor-vite-plugin", () => {
|
|
|
1842
1843
|
}
|
|
1843
1844
|
`;
|
|
1844
1845
|
const result = transform(code);
|
|
1845
|
-
// Both branches are i18n — no non-i18n text produced
|
|
1846
|
+
// Both branches are i18n — no non-i18n text produced, key resolved at runtime
|
|
1846
1847
|
expect(result).toContain('data-upstart-editable-text="true"');
|
|
1847
|
-
expect(result).toContain(
|
|
1848
|
+
expect(result).toContain(
|
|
1849
|
+
'data-upstart-i18n={isAdmin ? "translation:role.admin" : "translation:role.user"}',
|
|
1850
|
+
);
|
|
1848
1851
|
});
|
|
1849
1852
|
|
|
1850
1853
|
test("should still be editable when only whitespace {' '} separates Trans from nothing", () => {
|
|
@@ -1860,6 +1863,211 @@ describe("upstart-editor-vite-plugin", () => {
|
|
|
1860
1863
|
expect(result).toContain('data-upstart-i18n="translation:label"');
|
|
1861
1864
|
});
|
|
1862
1865
|
});
|
|
1866
|
+
|
|
1867
|
+
describe("i18n with static text affixes", () => {
|
|
1868
|
+
test("should be editable with a suffix when a bare asterisk follows Trans", () => {
|
|
1869
|
+
const code = `
|
|
1870
|
+
import { Trans } from "react-i18next";
|
|
1871
|
+
export default function App() {
|
|
1872
|
+
return (
|
|
1873
|
+
<label className="label">
|
|
1874
|
+
<Trans i18nKey="contact.form.phone" /> *
|
|
1875
|
+
</label>
|
|
1876
|
+
);
|
|
1877
|
+
}
|
|
1878
|
+
`;
|
|
1879
|
+
const result = transform(code);
|
|
1880
|
+
expect(result).toContain('data-upstart-editable-text="true"');
|
|
1881
|
+
expect(result).toContain('data-upstart-editable-text-mode="plain"');
|
|
1882
|
+
expect(result).toContain('data-upstart-i18n="translation:contact.form.phone"');
|
|
1883
|
+
expect(result).toContain('data-upstart-i18n-suffix=" *"');
|
|
1884
|
+
expect(result).not.toContain("data-upstart-i18n-prefix");
|
|
1885
|
+
});
|
|
1886
|
+
|
|
1887
|
+
test("should be editable with a suffix when the asterisk is wrapped in a static span", () => {
|
|
1888
|
+
const code = `
|
|
1889
|
+
import { Trans } from "react-i18next";
|
|
1890
|
+
export default function App() {
|
|
1891
|
+
return (
|
|
1892
|
+
<label className="label">
|
|
1893
|
+
<Trans i18nKey="contact.form.name" /> <span aria-hidden="true">*</span>
|
|
1894
|
+
</label>
|
|
1895
|
+
);
|
|
1896
|
+
}
|
|
1897
|
+
`;
|
|
1898
|
+
const result = transform(code);
|
|
1899
|
+
expect(result).toContain('data-upstart-editable-text="true"');
|
|
1900
|
+
expect(result).toContain('data-upstart-i18n="translation:contact.form.name"');
|
|
1901
|
+
expect(result).toContain('data-upstart-i18n-suffix=" *"');
|
|
1902
|
+
});
|
|
1903
|
+
|
|
1904
|
+
test("should capture a static prefix before Trans", () => {
|
|
1905
|
+
const code = `
|
|
1906
|
+
import { Trans } from "react-i18next";
|
|
1907
|
+
export default function App() {
|
|
1908
|
+
return <label>* <Trans i18nKey="form.city" /></label>;
|
|
1909
|
+
}
|
|
1910
|
+
`;
|
|
1911
|
+
const result = transform(code);
|
|
1912
|
+
expect(result).toContain('data-upstart-editable-text="true"');
|
|
1913
|
+
expect(result).toContain('data-upstart-i18n-prefix="* "');
|
|
1914
|
+
expect(result).not.toContain("data-upstart-i18n-suffix");
|
|
1915
|
+
});
|
|
1916
|
+
|
|
1917
|
+
test("should escape quotes in affixes", () => {
|
|
1918
|
+
const code = `
|
|
1919
|
+
import { Trans } from "react-i18next";
|
|
1920
|
+
export default function App() {
|
|
1921
|
+
return <label><Trans i18nKey="form.size" /> (")</label>;
|
|
1922
|
+
}
|
|
1923
|
+
`;
|
|
1924
|
+
const result = transform(code);
|
|
1925
|
+
expect(result).toContain('data-upstart-i18n-suffix=" (")"');
|
|
1926
|
+
});
|
|
1927
|
+
|
|
1928
|
+
test("should NOT emit affixes when there are two i18n sources around static text", () => {
|
|
1929
|
+
const code = `
|
|
1930
|
+
import { Trans } from "react-i18next";
|
|
1931
|
+
export default function App() {
|
|
1932
|
+
return <p><Trans i18nKey="a" /> / <Trans i18nKey="b" /></p>;
|
|
1933
|
+
}
|
|
1934
|
+
`;
|
|
1935
|
+
const result = transform(code);
|
|
1936
|
+
expect(result).not.toContain('data-upstart-editable-text="true"');
|
|
1937
|
+
expect(result).not.toContain("data-upstart-i18n-suffix");
|
|
1938
|
+
});
|
|
1939
|
+
|
|
1940
|
+
test("should NOT emit affixes when a dynamic expression sits next to Trans", () => {
|
|
1941
|
+
const code = `
|
|
1942
|
+
import { Trans } from "react-i18next";
|
|
1943
|
+
export default function App() {
|
|
1944
|
+
return <label><Trans i18nKey="form.count" /> ({count})</label>;
|
|
1945
|
+
}
|
|
1946
|
+
`;
|
|
1947
|
+
const result = transform(code);
|
|
1948
|
+
expect(result).not.toContain('data-upstart-editable-text="true"');
|
|
1949
|
+
expect(result).not.toContain("data-upstart-i18n-suffix");
|
|
1950
|
+
});
|
|
1951
|
+
|
|
1952
|
+
test("should NOT emit affixes when a sibling element is not purely static", () => {
|
|
1953
|
+
const code = `
|
|
1954
|
+
import { Trans } from "react-i18next";
|
|
1955
|
+
export default function App() {
|
|
1956
|
+
return <label><Trans i18nKey="form.city" /> <span>{hint}</span></label>;
|
|
1957
|
+
}
|
|
1958
|
+
`;
|
|
1959
|
+
const result = transform(code);
|
|
1960
|
+
expect(result).not.toContain('data-upstart-editable-text="true"');
|
|
1961
|
+
});
|
|
1962
|
+
|
|
1963
|
+
test("should NOT emit affixes when the element has no resolvable single key", () => {
|
|
1964
|
+
const code = `
|
|
1965
|
+
import { Trans } from "react-i18next";
|
|
1966
|
+
export default function App() {
|
|
1967
|
+
return <p><Trans i18nKey="a" /><Trans i18nKey="b" /></p>;
|
|
1968
|
+
}
|
|
1969
|
+
`;
|
|
1970
|
+
const result = transform(code);
|
|
1971
|
+
// Two translations render at once → no key can be resolved
|
|
1972
|
+
expect(result).not.toContain("data-upstart-i18n");
|
|
1973
|
+
expect(result).not.toContain('data-upstart-editable-text="true"');
|
|
1974
|
+
});
|
|
1975
|
+
|
|
1976
|
+
test("should emit affixes around a t() call too", () => {
|
|
1977
|
+
const code = `
|
|
1978
|
+
import { useTranslation } from "react-i18next";
|
|
1979
|
+
export default function App() {
|
|
1980
|
+
const { t } = useTranslation();
|
|
1981
|
+
return <label>{t("form.email")} *</label>;
|
|
1982
|
+
}
|
|
1983
|
+
`;
|
|
1984
|
+
const result = transform(code);
|
|
1985
|
+
expect(result).toContain('data-upstart-editable-text="true"');
|
|
1986
|
+
expect(result).toContain('data-upstart-i18n="translation:form.email"');
|
|
1987
|
+
expect(result).toContain('data-upstart-i18n-suffix=" *"');
|
|
1988
|
+
});
|
|
1989
|
+
});
|
|
1990
|
+
});
|
|
1991
|
+
|
|
1992
|
+
describe("Runtime-resolved i18n key (single key per element)", () => {
|
|
1993
|
+
test("should resolve the key from the condition for a submit button", () => {
|
|
1994
|
+
const code = `
|
|
1995
|
+
import { Trans } from "react-i18next";
|
|
1996
|
+
export default function App({ isSubmitting }) {
|
|
1997
|
+
return (
|
|
1998
|
+
<button type="submit" disabled={isSubmitting}>
|
|
1999
|
+
{isSubmitting ? <Trans i18nKey="form.submitting" /> : <Trans i18nKey="form.submit" />}
|
|
2000
|
+
</button>
|
|
2001
|
+
);
|
|
2002
|
+
}
|
|
2003
|
+
`;
|
|
2004
|
+
const result = transform(code);
|
|
2005
|
+
expect(result).toContain('data-upstart-editable-text="true"');
|
|
2006
|
+
expect(result).toContain(
|
|
2007
|
+
'data-upstart-i18n={isSubmitting ? "translation:form.submitting" : "translation:form.submit"}',
|
|
2008
|
+
);
|
|
2009
|
+
// Never a comma-separated list — the runtime cannot parse those
|
|
2010
|
+
expect(result).not.toMatch(/data-upstart-i18n="[^"]*,/);
|
|
2011
|
+
});
|
|
2012
|
+
|
|
2013
|
+
test("should keep a member-expression condition intact", () => {
|
|
2014
|
+
const code = `
|
|
2015
|
+
import { Trans } from "react-i18next";
|
|
2016
|
+
export default function App({ nav }) {
|
|
2017
|
+
return <span>{nav.state === "idle" ? <Trans i18nKey="a" /> : <Trans i18nKey="b" />}</span>;
|
|
2018
|
+
}
|
|
2019
|
+
`;
|
|
2020
|
+
const result = transform(code);
|
|
2021
|
+
expect(result).toContain(
|
|
2022
|
+
'data-upstart-i18n={nav.state === "idle" ? "translation:a" : "translation:b"}',
|
|
2023
|
+
);
|
|
2024
|
+
});
|
|
2025
|
+
|
|
2026
|
+
test("should mix a runtime-resolved key with a static suffix", () => {
|
|
2027
|
+
const code = `
|
|
2028
|
+
import { Trans } from "react-i18next";
|
|
2029
|
+
export default function App({ isSubmitting }) {
|
|
2030
|
+
return <label>{isSubmitting ? <Trans i18nKey="a" /> : <Trans i18nKey="b" />} *</label>;
|
|
2031
|
+
}
|
|
2032
|
+
`;
|
|
2033
|
+
const result = transform(code);
|
|
2034
|
+
expect(result).toContain('data-upstart-i18n-suffix=" *"');
|
|
2035
|
+
expect(result).toContain('data-upstart-i18n={isSubmitting ? "translation:a" : "translation:b"}');
|
|
2036
|
+
});
|
|
2037
|
+
|
|
2038
|
+
test("should NOT be editable when a Trans sits next to an i18n ternary", () => {
|
|
2039
|
+
const code = `
|
|
2040
|
+
import { Trans } from "react-i18next";
|
|
2041
|
+
export default function App({ flag }) {
|
|
2042
|
+
return <p><Trans i18nKey="lead" />{flag ? <Trans i18nKey="a" /> : <Trans i18nKey="b" />}</p>;
|
|
2043
|
+
}
|
|
2044
|
+
`;
|
|
2045
|
+
const result = transform(code);
|
|
2046
|
+
expect(result).not.toContain("data-upstart-i18n");
|
|
2047
|
+
expect(result).not.toContain('data-upstart-editable-text="true"');
|
|
2048
|
+
});
|
|
2049
|
+
|
|
2050
|
+
test("should NOT be editable when a ternary branch holds two translations", () => {
|
|
2051
|
+
const code = `
|
|
2052
|
+
import { Trans } from "react-i18next";
|
|
2053
|
+
export default function App({ flag }) {
|
|
2054
|
+
return <p>{flag ? <><Trans i18nKey="a" /><Trans i18nKey="b" /></> : <Trans i18nKey="c" />}</p>;
|
|
2055
|
+
}
|
|
2056
|
+
`;
|
|
2057
|
+
const result = transform(code);
|
|
2058
|
+
expect(result).not.toContain("data-upstart-i18n=");
|
|
2059
|
+
});
|
|
2060
|
+
|
|
2061
|
+
test("should still emit a plain static key for a single translation", () => {
|
|
2062
|
+
const code = `
|
|
2063
|
+
import { Trans } from "react-i18next";
|
|
2064
|
+
export default function App() {
|
|
2065
|
+
return <h1><Trans i18nKey="site.title" /></h1>;
|
|
2066
|
+
}
|
|
2067
|
+
`;
|
|
2068
|
+
const result = transform(code);
|
|
2069
|
+
expect(result).toContain('data-upstart-i18n="translation:site.title"');
|
|
2070
|
+
});
|
|
1863
2071
|
});
|
|
1864
2072
|
|
|
1865
2073
|
describe("useTranslation t() Function Detection", () => {
|
|
@@ -1921,7 +2129,9 @@ describe("upstart-editor-vite-plugin", () => {
|
|
|
1921
2129
|
}
|
|
1922
2130
|
`;
|
|
1923
2131
|
const result = transform(code);
|
|
1924
|
-
expect(result).toContain(
|
|
2132
|
+
expect(result).toContain(
|
|
2133
|
+
'data-upstart-i18n={isActive ? "translation:active" : "translation:inactive"}',
|
|
2134
|
+
);
|
|
1925
2135
|
});
|
|
1926
2136
|
|
|
1927
2137
|
test("should detect t() in logical expression", () => {
|
|
@@ -1961,7 +2171,7 @@ describe("upstart-editor-vite-plugin", () => {
|
|
|
1961
2171
|
expect(result).toContain('data-upstart-i18n="translation:features.title"');
|
|
1962
2172
|
});
|
|
1963
2173
|
|
|
1964
|
-
test("should
|
|
2174
|
+
test("should NOT be editable when a t() call and a Trans render side by side", () => {
|
|
1965
2175
|
const code = `
|
|
1966
2176
|
import { useTranslation } from "react-i18next";
|
|
1967
2177
|
import { Trans } from "react-i18next";
|
|
@@ -1971,8 +2181,9 @@ describe("upstart-editor-vite-plugin", () => {
|
|
|
1971
2181
|
}
|
|
1972
2182
|
`;
|
|
1973
2183
|
const result = transform(code);
|
|
1974
|
-
|
|
1975
|
-
expect(result).toContain(
|
|
2184
|
+
// Both translations render at once: an inline edit could not be routed to a key
|
|
2185
|
+
expect(result).not.toContain("data-upstart-i18n");
|
|
2186
|
+
expect(result).not.toContain('data-upstart-editable-text="true"');
|
|
1976
2187
|
});
|
|
1977
2188
|
|
|
1978
2189
|
test("should detect t() inside .map() callback on child element", () => {
|