mirror of
https://repo.dactyloidae.xyz/Dactyloidae/UXP.git
synced 2026-10-31 19:47:32 +09:00
Merge remote-tracking branch 'origin/master' into custom
This commit is contained in:
commit
84282125cf
16 changed files with 98 additions and 16 deletions
|
|
@ -29,6 +29,7 @@
|
||||||
<ms_asmv3:application xmlns:ms_asmv3="urn:schemas-microsoft-com:asm.v3">
|
<ms_asmv3:application xmlns:ms_asmv3="urn:schemas-microsoft-com:asm.v3">
|
||||||
<ms_asmv3:windowsSettings xmlns="http://schemas.microsoft.com/SMI/2005/WindowsSettings">
|
<ms_asmv3:windowsSettings xmlns="http://schemas.microsoft.com/SMI/2005/WindowsSettings">
|
||||||
<dpiAware>True/PM</dpiAware>
|
<dpiAware>True/PM</dpiAware>
|
||||||
|
<dpiAwareness xmlns="http://schemas.microsoft.com/SMI/2016/WindowsSettings">PerMonitorV2,PerMonitor</dpiAwareness>
|
||||||
</ms_asmv3:windowsSettings>
|
</ms_asmv3:windowsSettings>
|
||||||
</ms_asmv3:application>
|
</ms_asmv3:application>
|
||||||
<compatibility xmlns="urn:schemas-microsoft-com:compatibility.v1">
|
<compatibility xmlns="urn:schemas-microsoft-com:compatibility.v1">
|
||||||
|
|
|
||||||
|
|
@ -29,6 +29,7 @@
|
||||||
<ms_asmv3:application xmlns:ms_asmv3="urn:schemas-microsoft-com:asm.v3">
|
<ms_asmv3:application xmlns:ms_asmv3="urn:schemas-microsoft-com:asm.v3">
|
||||||
<ms_asmv3:windowsSettings xmlns="http://schemas.microsoft.com/SMI/2005/WindowsSettings">
|
<ms_asmv3:windowsSettings xmlns="http://schemas.microsoft.com/SMI/2005/WindowsSettings">
|
||||||
<dpiAware>True/PM</dpiAware>
|
<dpiAware>True/PM</dpiAware>
|
||||||
|
<dpiAwareness xmlns="http://schemas.microsoft.com/SMI/2016/WindowsSettings">PerMonitorV2,PerMonitor</dpiAwareness>
|
||||||
</ms_asmv3:windowsSettings>
|
</ms_asmv3:windowsSettings>
|
||||||
</ms_asmv3:application>
|
</ms_asmv3:application>
|
||||||
<compatibility xmlns="urn:schemas-microsoft-com:compatibility.v1">
|
<compatibility xmlns="urn:schemas-microsoft-com:compatibility.v1">
|
||||||
|
|
|
||||||
|
|
@ -144,8 +144,13 @@ pref("app.update.cert.maxErrors", 5);
|
||||||
// |app.update.url.override| user preference has been set for testing updates or
|
// |app.update.url.override| user preference has been set for testing updates or
|
||||||
// when the |app.update.cert.checkAttributes| preference is set to false. Also,
|
// when the |app.update.cert.checkAttributes| preference is set to false. Also,
|
||||||
// the |app.update.url.override| preference should ONLY be used for testing.
|
// the |app.update.url.override| preference should ONLY be used for testing.
|
||||||
pref("app.update.certs.1.issuerName", "CN=COMODO RSA Domain Validation Secure Server CA,O=COMODO CA Limited,L=Salford,ST=Greater Manchester,C=GB");
|
//
|
||||||
pref("app.update.certs.1.commonName", "*.palemoon.org");
|
// Examples:
|
||||||
|
// pref("app.update.certs.1.issuerName", "CN=COMODO RSA Domain Validation Secure Server CA,O=COMODO CA Limited,L=Salford,ST=Greater Manchester,C=GB");
|
||||||
|
// pref("app.update.certs.1.commonName", "*.palemoon.org");
|
||||||
|
//
|
||||||
|
// Note: these preferences are branding-specific and should be listed in
|
||||||
|
// application branding, depending on publisher.
|
||||||
|
|
||||||
// Whether or not app updates are enabled
|
// Whether or not app updates are enabled
|
||||||
pref("app.update.enabled", true);
|
pref("app.update.enabled", true);
|
||||||
|
|
|
||||||
|
|
@ -31,7 +31,7 @@ pref("@GUAO_PREF@.msn.com","Mozilla/5.0 (%OS_SLICE% rv:@GK_VERSION@) @GK_SLICE@
|
||||||
pref("@GUAO_PREF@.patientaccess.com","Mozilla/5.0 (%OS_SLICE% rv:60.0) @GK_SLICE@ Firefox/60.0 @PM_SLICE@");
|
pref("@GUAO_PREF@.patientaccess.com","Mozilla/5.0 (%OS_SLICE% rv:60.0) @GK_SLICE@ Firefox/60.0 @PM_SLICE@");
|
||||||
pref("@GUAO_PREF@.outlook.com","Mozilla/5.0 (%OS_SLICE% rv:@GK_VERSION@) @GK_SLICE@ @FX_SLICE@ (Pale Moon)");
|
pref("@GUAO_PREF@.outlook.com","Mozilla/5.0 (%OS_SLICE% rv:@GK_VERSION@) @GK_SLICE@ @FX_SLICE@ (Pale Moon)");
|
||||||
pref("@GUAO_PREF@.web.de","Mozilla/5.0 (%OS_SLICE% rv:@GK_VERSION@) @GK_SLICE@ @FX_SLICE@ (Pale Moon)");
|
pref("@GUAO_PREF@.web.de","Mozilla/5.0 (%OS_SLICE% rv:@GK_VERSION@) @GK_SLICE@ @FX_SLICE@ (Pale Moon)");
|
||||||
pref("@GUAO_PREF@.yahoo.com","Mozilla/5.0 (%OS_SLICE% rv:99.9) @GK_SLICE@ Firefox/99.9 (Pale Moon)");
|
pref("@GUAO_PREF@.yahoo.com","Mozilla/5.0 (%OS_SLICE% rv:99.9) @GK_SLICE@ Firefox/99.9");
|
||||||
pref("@GUAO_PREF@.calendar.yahoo.com","Mozilla/5.0 (%OS_SLICE% rv:@GK_VERSION@) @GK_SLICE@ @FX_SLICE@ (Pale Moon)");
|
pref("@GUAO_PREF@.calendar.yahoo.com","Mozilla/5.0 (%OS_SLICE% rv:@GK_VERSION@) @GK_SLICE@ @FX_SLICE@ (Pale Moon)");
|
||||||
pref("@GUAO_PREF@.youtube.com","Mozilla/5.0 (%OS_SLICE% rv:60.0) @GK_SLICE@ Firefox/60.0 @PM_SLICE@");
|
pref("@GUAO_PREF@.youtube.com","Mozilla/5.0 (%OS_SLICE% rv:60.0) @GK_SLICE@ Firefox/60.0 @PM_SLICE@");
|
||||||
pref("@GUAO_PREF@.gaming.youtube.com","Mozilla/5.0 (%OS_SLICE% rv:42.0) @GK_SLICE@ Firefox/42.0");
|
pref("@GUAO_PREF@.gaming.youtube.com","Mozilla/5.0 (%OS_SLICE% rv:42.0) @GK_SLICE@ Firefox/42.0");
|
||||||
|
|
|
||||||
|
|
@ -7857,6 +7857,7 @@ exports.CSS_PROPERTIES = {
|
||||||
],
|
],
|
||||||
"supports": [],
|
"supports": [],
|
||||||
"values": [
|
"values": [
|
||||||
|
"anywhere",
|
||||||
"break-word",
|
"break-word",
|
||||||
"inherit",
|
"inherit",
|
||||||
"initial",
|
"initial",
|
||||||
|
|
@ -9317,6 +9318,7 @@ exports.CSS_PROPERTIES = {
|
||||||
],
|
],
|
||||||
"supports": [],
|
"supports": [],
|
||||||
"values": [
|
"values": [
|
||||||
|
"anywhere",
|
||||||
"break-word",
|
"break-word",
|
||||||
"inherit",
|
"inherit",
|
||||||
"initial",
|
"initial",
|
||||||
|
|
|
||||||
|
|
@ -1071,6 +1071,34 @@ gfxTextRun::GetAdvanceWidth(Range aRange, PropertyProvider *aProvider,
|
||||||
return result + GetAdvanceForGlyphs(ligatureRange);
|
return result + GetAdvanceForGlyphs(ligatureRange);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
gfxFloat
|
||||||
|
gfxTextRun::GetMinAdvanceWidth(Range aRange)
|
||||||
|
{
|
||||||
|
MOZ_ASSERT(aRange.end <= GetLength(), "Substring out of range");
|
||||||
|
|
||||||
|
Range ligatureRange = aRange;
|
||||||
|
ShrinkToLigatureBoundaries(&ligatureRange);
|
||||||
|
|
||||||
|
gfxFloat result = std::max(
|
||||||
|
ComputePartialLigatureWidth(Range(aRange.start, ligatureRange.start),
|
||||||
|
nullptr),
|
||||||
|
ComputePartialLigatureWidth(Range(ligatureRange.end, aRange.end),
|
||||||
|
nullptr));
|
||||||
|
|
||||||
|
// XXX Do we need to take spacing into account? When each grapheme cluster
|
||||||
|
// takes its own line, we shouldn't be adding spacings around them.
|
||||||
|
gfxFloat clusterAdvance = 0;
|
||||||
|
for (uint32_t i = ligatureRange.start; i < ligatureRange.end; ++i) {
|
||||||
|
clusterAdvance += GetAdvanceForGlyph(i);
|
||||||
|
if (i + 1 == ligatureRange.end || IsClusterStart(i + 1)) {
|
||||||
|
result = std::max(result, clusterAdvance);
|
||||||
|
clusterAdvance = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
bool
|
bool
|
||||||
gfxTextRun::SetLineBreaks(Range aRange,
|
gfxTextRun::SetLineBreaks(Range aRange,
|
||||||
bool aLineBreakBefore, bool aLineBreakAfter,
|
bool aLineBreakBefore, bool aLineBreakAfter,
|
||||||
|
|
|
||||||
|
|
@ -297,6 +297,12 @@ public:
|
||||||
return GetAdvanceWidth(Range(this), nullptr);
|
return GetAdvanceWidth(Range(this), nullptr);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Computes the minimum advance width for a substring assuming line
|
||||||
|
* breaking is allowed everywhere.
|
||||||
|
*/
|
||||||
|
gfxFloat GetMinAdvanceWidth(Range aRange);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Clear all stored line breaks for the given range (both before and after),
|
* Clear all stored line breaks for the given range (both before and after),
|
||||||
* and then set the line-break state before aRange.start to aBreakBefore and
|
* and then set the line-break state before aRange.start to aBreakBefore and
|
||||||
|
|
|
||||||
|
|
@ -29,6 +29,7 @@
|
||||||
<ms_asmv3:application xmlns:ms_asmv3="urn:schemas-microsoft-com:asm.v3">
|
<ms_asmv3:application xmlns:ms_asmv3="urn:schemas-microsoft-com:asm.v3">
|
||||||
<ms_asmv3:windowsSettings xmlns="http://schemas.microsoft.com/SMI/2005/WindowsSettings">
|
<ms_asmv3:windowsSettings xmlns="http://schemas.microsoft.com/SMI/2005/WindowsSettings">
|
||||||
<dpiAware>True/PM</dpiAware>
|
<dpiAware>True/PM</dpiAware>
|
||||||
|
<dpiAwareness xmlns="http://schemas.microsoft.com/SMI/2016/WindowsSettings">PerMonitorV2,PerMonitor</dpiAwareness>
|
||||||
</ms_asmv3:windowsSettings>
|
</ms_asmv3:windowsSettings>
|
||||||
</ms_asmv3:application>
|
</ms_asmv3:application>
|
||||||
<compatibility xmlns="urn:schemas-microsoft-com:compatibility.v1">
|
<compatibility xmlns="urn:schemas-microsoft-com:compatibility.v1">
|
||||||
|
|
|
||||||
|
|
@ -8243,6 +8243,17 @@ nsTextFrame::AddInlineMinISizeForFlow(nsRenderingContext *aRenderingContext,
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// If overflow-wrap is 'anywhere', we can wrap everywhere.
|
||||||
|
if (textStyle->mOverflowWrap == NS_STYLE_OVERFLOWWRAP_ANYWHERE &&
|
||||||
|
textStyle->WordCanWrap(this)) {
|
||||||
|
aData->OptionallyBreak();
|
||||||
|
aData->mCurrentLine +=
|
||||||
|
textRun->GetMinAdvanceWidth(Range(start, flowEndInTextRun));
|
||||||
|
aData->mTrailingWhitespace = 0;
|
||||||
|
aData->OptionallyBreak();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
AutoTArray<bool,BIG_TEXT_NODE_SIZE> hyphBuffer;
|
AutoTArray<bool,BIG_TEXT_NODE_SIZE> hyphBuffer;
|
||||||
bool *hyphBreakBefore = nullptr;
|
bool *hyphBreakBefore = nullptr;
|
||||||
if (hyphenating) {
|
if (hyphenating) {
|
||||||
|
|
|
||||||
|
|
@ -144,6 +144,7 @@ CSS_KEY(alternate, alternate)
|
||||||
CSS_KEY(alternate-reverse, alternate_reverse)
|
CSS_KEY(alternate-reverse, alternate_reverse)
|
||||||
CSS_KEY(always, always)
|
CSS_KEY(always, always)
|
||||||
CSS_KEY(annotation, annotation)
|
CSS_KEY(annotation, annotation)
|
||||||
|
CSS_KEY(anywhere, anywhere)
|
||||||
CSS_KEY(appworkspace, appworkspace)
|
CSS_KEY(appworkspace, appworkspace)
|
||||||
CSS_KEY(auto, auto)
|
CSS_KEY(auto, auto)
|
||||||
CSS_KEY(auto-fill, auto_fill)
|
CSS_KEY(auto-fill, auto_fill)
|
||||||
|
|
|
||||||
|
|
@ -2284,6 +2284,7 @@ const KTableEntry nsCSSProps::kWordBreakKTable[] = {
|
||||||
const KTableEntry nsCSSProps::kOverflowWrapKTable[] = {
|
const KTableEntry nsCSSProps::kOverflowWrapKTable[] = {
|
||||||
{ eCSSKeyword_normal, NS_STYLE_OVERFLOWWRAP_NORMAL },
|
{ eCSSKeyword_normal, NS_STYLE_OVERFLOWWRAP_NORMAL },
|
||||||
{ eCSSKeyword_break_word, NS_STYLE_OVERFLOWWRAP_BREAK_WORD },
|
{ eCSSKeyword_break_word, NS_STYLE_OVERFLOWWRAP_BREAK_WORD },
|
||||||
|
{ eCSSKeyword_anywhere, NS_STYLE_OVERFLOWWRAP_ANYWHERE },
|
||||||
{ eCSSKeyword_UNKNOWN, -1 }
|
{ eCSSKeyword_UNKNOWN, -1 }
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -997,6 +997,7 @@ enum class StyleDisplay : uint8_t {
|
||||||
// See nsStyleText
|
// See nsStyleText
|
||||||
#define NS_STYLE_OVERFLOWWRAP_NORMAL 0
|
#define NS_STYLE_OVERFLOWWRAP_NORMAL 0
|
||||||
#define NS_STYLE_OVERFLOWWRAP_BREAK_WORD 1
|
#define NS_STYLE_OVERFLOWWRAP_BREAK_WORD 1
|
||||||
|
#define NS_STYLE_OVERFLOWWRAP_ANYWHERE 2
|
||||||
|
|
||||||
// See nsStyleText
|
// See nsStyleText
|
||||||
#define NS_STYLE_HYPHENS_NONE 0
|
#define NS_STYLE_HYPHENS_NONE 0
|
||||||
|
|
|
||||||
|
|
@ -2133,8 +2133,11 @@ struct MOZ_NEEDS_MEMMOVABLE_MEMBERS nsStyleText
|
||||||
}
|
}
|
||||||
|
|
||||||
bool WordCanWrapStyle() const {
|
bool WordCanWrapStyle() const {
|
||||||
return WhiteSpaceCanWrapStyle() &&
|
if (!WhiteSpaceCanWrapStyle()) {
|
||||||
mOverflowWrap == NS_STYLE_OVERFLOWWRAP_BREAK_WORD;
|
return false;
|
||||||
|
}
|
||||||
|
return (mOverflowWrap == NS_STYLE_OVERFLOWWRAP_BREAK_WORD ||
|
||||||
|
mOverflowWrap == NS_STYLE_OVERFLOWWRAP_ANYWHERE);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool HasTextEmphasis() const {
|
bool HasTextEmphasis() const {
|
||||||
|
|
|
||||||
|
|
@ -482,10 +482,20 @@ WinUtils::Initialize()
|
||||||
if (IsWin10OrLater()) {
|
if (IsWin10OrLater()) {
|
||||||
HMODULE user32Dll = ::GetModuleHandleW(L"user32");
|
HMODULE user32Dll = ::GetModuleHandleW(L"user32");
|
||||||
if (user32Dll) {
|
if (user32Dll) {
|
||||||
sEnableNonClientDpiScaling = (EnableNonClientDpiScalingProc)
|
auto getThreadDpiAwarenessContext = (decltype(GetThreadDpiAwarenessContext)*)
|
||||||
::GetProcAddress(user32Dll, "EnableNonClientDpiScaling");
|
::GetProcAddress(user32Dll, "GetThreadDpiAwarenessContext");
|
||||||
sSetThreadDpiAwarenessContext = (SetThreadDpiAwarenessContextProc)
|
auto areDpiAwarenessContextsEqual = (decltype(AreDpiAwarenessContextsEqual)*)
|
||||||
::GetProcAddress(user32Dll, "SetThreadDpiAwarenessContext");
|
::GetProcAddress(user32Dll, "AreDpiAwarenessContextsEqual");
|
||||||
|
if (getThreadDpiAwarenessContext && areDpiAwarenessContextsEqual &&
|
||||||
|
areDpiAwarenessContextsEqual(getThreadDpiAwarenessContext(),
|
||||||
|
DPI_AWARENESS_CONTEXT_PER_MONITOR_AWARE)) {
|
||||||
|
// Only per-monitor DPI awareness v1 requires these workarounds.
|
||||||
|
// Since this was introduced in Win 8.1 we'll need to keep this indefinitely.
|
||||||
|
sEnableNonClientDpiScaling = (EnableNonClientDpiScalingProc)
|
||||||
|
::GetProcAddress(user32Dll, "EnableNonClientDpiScaling");
|
||||||
|
sSetThreadDpiAwarenessContext = (SetThreadDpiAwarenessContextProc)
|
||||||
|
::GetProcAddress(user32Dll, "SetThreadDpiAwarenessContext");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -501,7 +511,7 @@ LRESULT WINAPI
|
||||||
WinUtils::NonClientDpiScalingDefWindowProcW(HWND hWnd, UINT msg,
|
WinUtils::NonClientDpiScalingDefWindowProcW(HWND hWnd, UINT msg,
|
||||||
WPARAM wParam, LPARAM lParam)
|
WPARAM wParam, LPARAM lParam)
|
||||||
{
|
{
|
||||||
if (msg == WM_NCCREATE && sEnableNonClientDpiScaling) {
|
if (msg == WM_NCCREATE) {
|
||||||
sEnableNonClientDpiScaling(hWnd);
|
sEnableNonClientDpiScaling(hWnd);
|
||||||
}
|
}
|
||||||
return ::DefWindowProcW(hWnd, msg, wParam, lParam);
|
return ::DefWindowProcW(hWnd, msg, wParam, lParam);
|
||||||
|
|
|
||||||
|
|
@ -96,6 +96,11 @@ typedef enum DPI_AWARENESS {
|
||||||
#define DPI_AWARENESS_CONTEXT_DECLARED
|
#define DPI_AWARENESS_CONTEXT_DECLARED
|
||||||
#endif // (DPI_AWARENESS_CONTEXT_DECLARED)
|
#endif // (DPI_AWARENESS_CONTEXT_DECLARED)
|
||||||
|
|
||||||
|
#if WINVER < 0x0605
|
||||||
|
WINUSERAPI DPI_AWARENESS_CONTEXT WINAPI GetThreadDpiAwarenessContext();
|
||||||
|
WINUSERAPI BOOL WINAPI
|
||||||
|
AreDpiAwarenessContextsEqual(DPI_AWARENESS_CONTEXT, DPI_AWARENESS_CONTEXT);
|
||||||
|
#endif /* WINVER < 0x0605 */
|
||||||
typedef DPI_AWARENESS_CONTEXT(WINAPI * SetThreadDpiAwarenessContextProc)(DPI_AWARENESS_CONTEXT);
|
typedef DPI_AWARENESS_CONTEXT(WINAPI * SetThreadDpiAwarenessContextProc)(DPI_AWARENESS_CONTEXT);
|
||||||
typedef BOOL(WINAPI * EnableNonClientDpiScalingProc)(HWND);
|
typedef BOOL(WINAPI * EnableNonClientDpiScalingProc)(HWND);
|
||||||
|
|
||||||
|
|
@ -152,6 +157,12 @@ class WinUtils
|
||||||
static SetThreadDpiAwarenessContextProc sSetThreadDpiAwarenessContext;
|
static SetThreadDpiAwarenessContextProc sSetThreadDpiAwarenessContext;
|
||||||
static EnableNonClientDpiScalingProc sEnableNonClientDpiScaling;
|
static EnableNonClientDpiScalingProc sEnableNonClientDpiScaling;
|
||||||
|
|
||||||
|
// Wrapper for DefWindowProc that will enable non-client dpi scaling on the
|
||||||
|
// window during creation.
|
||||||
|
static LRESULT WINAPI
|
||||||
|
NonClientDpiScalingDefWindowProcW(HWND hWnd, UINT msg,
|
||||||
|
WPARAM wParam, LPARAM lParam);
|
||||||
|
|
||||||
public:
|
public:
|
||||||
class AutoSystemDpiAware
|
class AutoSystemDpiAware
|
||||||
{
|
{
|
||||||
|
|
@ -174,11 +185,11 @@ public:
|
||||||
DPI_AWARENESS_CONTEXT mPrevContext;
|
DPI_AWARENESS_CONTEXT mPrevContext;
|
||||||
};
|
};
|
||||||
|
|
||||||
// Wrapper for DefWindowProc that will enable non-client dpi scaling on the
|
static decltype(::DefWindowProcW)* GetDefWindowProc() {
|
||||||
// window during creation.
|
return sEnableNonClientDpiScaling ?
|
||||||
static LRESULT WINAPI
|
NonClientDpiScalingDefWindowProcW :
|
||||||
NonClientDpiScalingDefWindowProcW(HWND hWnd, UINT msg,
|
::DefWindowProcW;
|
||||||
WPARAM wParam, LPARAM lParam);
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get the system's default logical-to-physical DPI scaling factor,
|
* Get the system's default logical-to-physical DPI scaling factor,
|
||||||
|
|
|
||||||
|
|
@ -1007,7 +1007,7 @@ nsWindow::RegisterWindowClass(const wchar_t* aClassName,
|
||||||
}
|
}
|
||||||
|
|
||||||
wc.style = CS_DBLCLKS | aExtraStyle;
|
wc.style = CS_DBLCLKS | aExtraStyle;
|
||||||
wc.lpfnWndProc = WinUtils::NonClientDpiScalingDefWindowProcW;
|
wc.lpfnWndProc = WinUtils::GetDefWindowProc();
|
||||||
wc.cbClsExtra = 0;
|
wc.cbClsExtra = 0;
|
||||||
wc.cbWndExtra = 0;
|
wc.cbWndExtra = 0;
|
||||||
wc.hInstance = nsToolkit::mDllInstance;
|
wc.hInstance = nsToolkit::mDllInstance;
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue